mirror of https://github.com/VLSIDA/OpenRAM.git
Cleanup of router.
Made offsets in geometry snap to grid. Changed gds_write to use list for visited flag. Rewrite self.gds each call in case of any changes.
This commit is contained in:
parent
7432192e5e
commit
985d04d4b5
|
|
@ -53,3 +53,14 @@ class design(hierarchy_design):
|
||||||
for inst in self.insts:
|
for inst in self.insts:
|
||||||
total_module_power += inst.mod.analytical_power(proc, vdd, temp, load)
|
total_module_power += inst.mod.analytical_power(proc, vdd, temp, load)
|
||||||
return total_module_power
|
return total_module_power
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
""" override print function output """
|
||||||
|
pins = ",".join(self.pins)
|
||||||
|
insts = [" {}".format(x) for x in self.insts]
|
||||||
|
objs = [" {}".format(x) for x in self.objs]
|
||||||
|
s = "********** design {0} **********\n".format(self.name)
|
||||||
|
s += "\n pins ({0})={1}\n".format(len(self.pins), pins)
|
||||||
|
s += "\n objs ({0})=\n{1}".format(len(self.objs), "\n".join(objs))
|
||||||
|
s += "\n insts ({0})=\n{1}\n".format(len(self.insts), "\n".join(insts))
|
||||||
|
return s
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ from vector import vector
|
||||||
import tech
|
import tech
|
||||||
import math
|
import math
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
from utils import round_to_grid
|
||||||
|
|
||||||
class geometry:
|
class geometry:
|
||||||
"""
|
"""
|
||||||
|
|
@ -46,8 +47,8 @@ class geometry:
|
||||||
def normalize(self):
|
def normalize(self):
|
||||||
""" Re-find the LL and UR points after a transform """
|
""" Re-find the LL and UR points after a transform """
|
||||||
(first,second)=self.boundary
|
(first,second)=self.boundary
|
||||||
ll = vector(min(first[0],second[0]),min(first[1],second[1]))
|
ll = vector(min(first[0],second[0]),min(first[1],second[1])).snap_to_grid()
|
||||||
ur = vector(max(first[0],second[0]),max(first[1],second[1]))
|
ur = vector(max(first[0],second[0]),max(first[1],second[1])).snap_to_grid()
|
||||||
self.boundary=[ll,ur]
|
self.boundary=[ll,ur]
|
||||||
|
|
||||||
def update_boundary(self):
|
def update_boundary(self):
|
||||||
|
|
@ -142,8 +143,8 @@ class instance(geometry):
|
||||||
self.rotate = rotate
|
self.rotate = rotate
|
||||||
self.offset = vector(offset).snap_to_grid()
|
self.offset = vector(offset).snap_to_grid()
|
||||||
self.mirror = mirror
|
self.mirror = mirror
|
||||||
self.width = mod.width
|
self.width = round_to_grid(mod.width)
|
||||||
self.height = mod.height
|
self.height = round_to_grid(mod.height)
|
||||||
self.compute_boundary(offset,mirror,rotate)
|
self.compute_boundary(offset,mirror,rotate)
|
||||||
|
|
||||||
debug.info(4, "creating instance: " + self.name)
|
debug.info(4, "creating instance: " + self.name)
|
||||||
|
|
@ -191,15 +192,15 @@ class instance(geometry):
|
||||||
self.mod.gds_write_file(self.gds)
|
self.mod.gds_write_file(self.gds)
|
||||||
# now write an instance of my module/structure
|
# now write an instance of my module/structure
|
||||||
new_layout.addInstance(self.gds,
|
new_layout.addInstance(self.gds,
|
||||||
offsetInMicrons=self.offset,
|
offsetInMicrons=self.offset,
|
||||||
mirror=self.mirror,
|
mirror=self.mirror,
|
||||||
rotate=self.rotate)
|
rotate=self.rotate)
|
||||||
|
|
||||||
def place(self, offset, mirror="R0", rotate=0):
|
def place(self, offset, mirror="R0", rotate=0):
|
||||||
""" This updates the placement of an instance. """
|
""" This updates the placement of an instance. """
|
||||||
debug.info(3, "placing instance {}".format(self.name))
|
debug.info(3, "placing instance {}".format(self.name))
|
||||||
# Update the placement of an already added instance
|
# Update the placement of an already added instance
|
||||||
self.offset = vector(offset)
|
self.offset = vector(offset).snap_to_grid()
|
||||||
self.mirror = mirror
|
self.mirror = mirror
|
||||||
self.rotate = rotate
|
self.rotate = rotate
|
||||||
self.update_boundary()
|
self.update_boundary()
|
||||||
|
|
@ -238,7 +239,7 @@ class instance(geometry):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
""" override print function output """
|
""" override print function output """
|
||||||
return "inst: " + self.name + " mod=" + self.mod.name
|
return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
""" override print function output """
|
""" override print function output """
|
||||||
|
|
@ -260,13 +261,13 @@ class path(geometry):
|
||||||
# supported right now. It might not work in gdsMill.
|
# supported right now. It might not work in gdsMill.
|
||||||
assert(0)
|
assert(0)
|
||||||
|
|
||||||
def gds_write_file(self, newLayout):
|
def gds_write_file(self, new_layout):
|
||||||
"""Writes the path to GDS"""
|
"""Writes the path to GDS"""
|
||||||
debug.info(4, "writing path (" + str(self.layerNumber) + "): " + self.coordinates)
|
debug.info(4, "writing path (" + str(self.layerNumber) + "): " + self.coordinates)
|
||||||
newLayout.addPath(layerNumber=self.layerNumber,
|
new_layout.addPath(layerNumber=self.layerNumber,
|
||||||
purposeNumber=0,
|
purposeNumber=0,
|
||||||
coordinates=self.coordinates,
|
coordinates=self.coordinates,
|
||||||
width=self.path_width)
|
width=self.path_width)
|
||||||
|
|
||||||
def get_blockages(self, layer):
|
def get_blockages(self, layer):
|
||||||
""" Fail since we don't support paths yet. """
|
""" Fail since we don't support paths yet. """
|
||||||
|
|
@ -301,15 +302,15 @@ class label(geometry):
|
||||||
|
|
||||||
debug.info(4,"creating label " + self.text + " " + str(self.layerNumber) + " " + str(self.offset))
|
debug.info(4,"creating label " + self.text + " " + str(self.layerNumber) + " " + str(self.offset))
|
||||||
|
|
||||||
def gds_write_file(self, newLayout):
|
def gds_write_file(self, new_layout):
|
||||||
"""Writes the text label to GDS"""
|
"""Writes the text label to GDS"""
|
||||||
debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text)
|
debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text)
|
||||||
newLayout.addText(text=self.text,
|
new_layout.addText(text=self.text,
|
||||||
layerNumber=self.layerNumber,
|
layerNumber=self.layerNumber,
|
||||||
purposeNumber=0,
|
purposeNumber=0,
|
||||||
offsetInMicrons=self.offset,
|
offsetInMicrons=self.offset,
|
||||||
magnification=self.zoom,
|
magnification=self.zoom,
|
||||||
rotate=None)
|
rotate=None)
|
||||||
|
|
||||||
def get_blockages(self, layer):
|
def get_blockages(self, layer):
|
||||||
""" Returns an empty list since text cannot be blockages. """
|
""" Returns an empty list since text cannot be blockages. """
|
||||||
|
|
@ -321,7 +322,7 @@ class label(geometry):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
""" override print function output """
|
""" override print function output """
|
||||||
return "( label: " + self.text + " @" + str(self.offset) + " layer=" + self.layerNumber + " )"
|
return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )"
|
||||||
|
|
||||||
class rectangle(geometry):
|
class rectangle(geometry):
|
||||||
"""Represents a rectangular shape"""
|
"""Represents a rectangular shape"""
|
||||||
|
|
@ -333,8 +334,8 @@ class rectangle(geometry):
|
||||||
self.layerNumber = layerNumber
|
self.layerNumber = layerNumber
|
||||||
self.offset = vector(offset).snap_to_grid()
|
self.offset = vector(offset).snap_to_grid()
|
||||||
self.size = vector(width, height).snap_to_grid()
|
self.size = vector(width, height).snap_to_grid()
|
||||||
self.width = self.size.x
|
self.width = round_to_grid(self.size.x)
|
||||||
self.height = self.size.y
|
self.height = round_to_grid(self.size.y)
|
||||||
self.compute_boundary(offset,"",0)
|
self.compute_boundary(offset,"",0)
|
||||||
|
|
||||||
debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): "
|
debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): "
|
||||||
|
|
@ -348,16 +349,16 @@ class rectangle(geometry):
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def gds_write_file(self, newLayout):
|
def gds_write_file(self, new_layout):
|
||||||
"""Writes the rectangular shape to GDS"""
|
"""Writes the rectangular shape to GDS"""
|
||||||
debug.info(4, "writing rectangle (" + str(self.layerNumber) + "):"
|
debug.info(4, "writing rectangle (" + str(self.layerNumber) + "):"
|
||||||
+ str(self.width) + "x" + str(self.height) + " @ " + str(self.offset))
|
+ str(self.width) + "x" + str(self.height) + " @ " + str(self.offset))
|
||||||
newLayout.addBox(layerNumber=self.layerNumber,
|
new_layout.addBox(layerNumber=self.layerNumber,
|
||||||
purposeNumber=0,
|
purposeNumber=0,
|
||||||
offsetInMicrons=self.offset,
|
offsetInMicrons=self.offset,
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=self.height,
|
height=self.height,
|
||||||
center=False)
|
center=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
""" override print function output """
|
""" override print function output """
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class layout(lef.lef):
|
||||||
self.insts = [] # Holds module/cell layout instances
|
self.insts = [] # Holds module/cell layout instances
|
||||||
self.objs = [] # Holds all other objects (labels, geometries, etc)
|
self.objs = [] # Holds all other objects (labels, geometries, etc)
|
||||||
self.pin_map = {} # Holds name->pin_layout map for all pins
|
self.pin_map = {} # Holds name->pin_layout map for all pins
|
||||||
self.visited = False # Flag for traversing the hierarchy
|
self.visited = [] # List of modules we have already visited
|
||||||
self.is_library_cell = False # Flag for library cells
|
self.is_library_cell = False # Flag for library cells
|
||||||
self.gds_read()
|
self.gds_read()
|
||||||
|
|
||||||
|
|
@ -432,59 +432,66 @@ class layout(lef.lef):
|
||||||
|
|
||||||
# open the gds file if it exists or else create a blank layout
|
# open the gds file if it exists or else create a blank layout
|
||||||
if os.path.isfile(self.gds_file):
|
if os.path.isfile(self.gds_file):
|
||||||
debug.info(3, "opening %s" % self.gds_file)
|
debug.info(3, "opening {}".format(self.gds_file))
|
||||||
self.is_library_cell=True
|
self.is_library_cell=True
|
||||||
self.gds = gdsMill.VlsiLayout(units=GDS["unit"])
|
self.gds = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||||
reader = gdsMill.Gds2reader(self.gds)
|
reader = gdsMill.Gds2reader(self.gds)
|
||||||
reader.loadFromFile(self.gds_file)
|
reader.loadFromFile(self.gds_file)
|
||||||
else:
|
else:
|
||||||
debug.info(4, "creating structure %s" % self.name)
|
debug.info(3, "Creating layout structure {}".format(self.name))
|
||||||
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
|
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
|
||||||
|
|
||||||
def print_gds(self, gds_file=None):
|
def print_gds(self, gds_file=None):
|
||||||
"""Print the gds file (not the vlsi class) to the terminal """
|
"""Print the gds file (not the vlsi class) to the terminal """
|
||||||
if gds_file == None:
|
if gds_file == None:
|
||||||
gds_file = self.gds_file
|
gds_file = self.gds_file
|
||||||
debug.info(4, "Printing %s" % gds_file)
|
debug.info(4, "Printing {}".format(gds_file))
|
||||||
arrayCellLayout = gdsMill.VlsiLayout(units=GDS["unit"])
|
arrayCellLayout = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||||
reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1)
|
reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1)
|
||||||
reader.loadFromFile(gds_file)
|
reader.loadFromFile(gds_file)
|
||||||
|
|
||||||
def clear_visited(self):
|
def clear_visited(self):
|
||||||
""" Recursively clear the visited flag """
|
""" Recursively clear the visited flag """
|
||||||
if not self.visited:
|
self.visited = []
|
||||||
for i in self.insts:
|
|
||||||
i.mod.clear_visited()
|
|
||||||
self.visited = False
|
|
||||||
|
|
||||||
def gds_write_file(self, newLayout):
|
def gds_write_file(self, gds_layout):
|
||||||
"""Recursive GDS write function"""
|
"""Recursive GDS write function"""
|
||||||
# Visited means that we already prepared self.gds for this subtree
|
# Visited means that we already prepared self.gds for this subtree
|
||||||
if self.visited:
|
if self.name in self.visited:
|
||||||
return
|
return
|
||||||
for i in self.insts:
|
for i in self.insts:
|
||||||
i.gds_write_file(newLayout)
|
i.gds_write_file(gds_layout)
|
||||||
for i in self.objs:
|
for i in self.objs:
|
||||||
i.gds_write_file(newLayout)
|
i.gds_write_file(gds_layout)
|
||||||
for pin_name in self.pin_map.keys():
|
for pin_name in self.pin_map.keys():
|
||||||
for pin in self.pin_map[pin_name]:
|
for pin in self.pin_map[pin_name]:
|
||||||
pin.gds_write_file(newLayout)
|
pin.gds_write_file(gds_layout)
|
||||||
self.visited = True
|
self.visited.append(self.name)
|
||||||
|
|
||||||
def gds_write(self, gds_name):
|
def gds_write(self, gds_name):
|
||||||
"""Write the entire gds of the object to the file."""
|
"""Write the entire gds of the object to the file."""
|
||||||
debug.info(3, "Writing to {0}".format(gds_name))
|
debug.info(3, "Writing to {}".format(gds_name))
|
||||||
|
|
||||||
|
# If we already wrote a GDS, we need to reset and traverse it again in
|
||||||
|
# case we made changes.
|
||||||
|
if not self.is_library_cell and self.visited:
|
||||||
|
debug.info(3, "Creating layout structure {}".format(self.name))
|
||||||
|
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
|
||||||
|
|
||||||
writer = gdsMill.Gds2writer(self.gds)
|
writer = gdsMill.Gds2writer(self.gds)
|
||||||
# MRG: 3/2/18 We don't want to clear the visited flag since
|
# MRG: 3/2/18 We don't want to clear the visited flag since
|
||||||
# this would result in duplicates of all instances being placed in self.gds
|
# this would result in duplicates of all instances being placed in self.gds
|
||||||
# which may have been previously processed!
|
# which may have been previously processed!
|
||||||
#self.clear_visited()
|
# MRG: 10/4/18 We need to clear if we make changes and write a second GDS!
|
||||||
|
self.clear_visited()
|
||||||
|
|
||||||
# recursively create all the remaining objects
|
# recursively create all the remaining objects
|
||||||
self.gds_write_file(self.gds)
|
self.gds_write_file(self.gds)
|
||||||
|
|
||||||
# populates the xyTree data structure for gds
|
# populates the xyTree data structure for gds
|
||||||
# self.gds.prepareForWrite()
|
# self.gds.prepareForWrite()
|
||||||
writer.writeToFile(gds_name)
|
writer.writeToFile(gds_name)
|
||||||
|
debug.info(3, "Done writing to {}".format(gds_name))
|
||||||
|
|
||||||
def get_boundary(self):
|
def get_boundary(self):
|
||||||
""" Return the lower-left and upper-right coordinates of boundary """
|
""" Return the lower-left and upper-right coordinates of boundary """
|
||||||
|
|
@ -1008,7 +1015,7 @@ class layout(lef.lef):
|
||||||
def pdf_write(self, pdf_name):
|
def pdf_write(self, pdf_name):
|
||||||
# NOTE: Currently does not work (Needs further research)
|
# NOTE: Currently does not work (Needs further research)
|
||||||
#self.pdf_name = self.name + ".pdf"
|
#self.pdf_name = self.name + ".pdf"
|
||||||
debug.info(0, "Writing to %s" % pdf_name)
|
debug.info(0, "Writing to {}".format(pdf_name))
|
||||||
pdf = gdsMill.pdfLayout(self.gds)
|
pdf = gdsMill.pdfLayout(self.gds)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ class options(optparse.Values):
|
||||||
# This is the name of the technology.
|
# This is the name of the technology.
|
||||||
tech_name = ""
|
tech_name = ""
|
||||||
# This is the temp directory where all intermediate results are stored.
|
# This is the temp directory where all intermediate results are stored.
|
||||||
openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid())
|
#openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid())
|
||||||
#openram_temp = "{0}/openram_temp/".format(os.getenv("HOME"))
|
openram_temp = "{0}/openram_temp/".format(os.getenv("HOME"))
|
||||||
# This is the verbosity level to control debug information. 0 is none, 1
|
# This is the verbosity level to control debug information. 0 is none, 1
|
||||||
# is minimal, etc.
|
# is minimal, etc.
|
||||||
debug_level = 0
|
debug_level = 0
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,6 @@ class grid:
|
||||||
self.map[n].path=value
|
self.map[n].path=value
|
||||||
|
|
||||||
def clear_blockages(self):
|
def clear_blockages(self):
|
||||||
debug.info(2,"Clearing all blockages")
|
|
||||||
self.set_blocked(set(self.map.keys()),False)
|
self.set_blocked(set(self.map.keys()),False)
|
||||||
|
|
||||||
def set_source(self,n,value=True):
|
def set_source(self,n,value=True):
|
||||||
|
|
|
||||||
|
|
@ -17,26 +17,28 @@ class router:
|
||||||
It populates blockages on a grid class.
|
It populates blockages on a grid class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, gds_name=None, module=None):
|
def __init__(self, layers, design, gds_filename=None):
|
||||||
"""Use the gds file or the cell for the blockages with the top module topName and
|
|
||||||
layers for the layers to route on
|
|
||||||
"""
|
"""
|
||||||
self.gds_name = gds_name
|
This will instantiate a copy of the gds file or the module at (0,0) and
|
||||||
self.module = module
|
route on top of this. The blockages from the gds/module will be considered.
|
||||||
debug.check(not (gds_name and module), "Specify only a GDS file or module")
|
"""
|
||||||
|
self.cell = design
|
||||||
|
|
||||||
# If we specified a module instead, write it out to read the gds
|
# If didn't specify a gds blockage file, write it out to read the gds
|
||||||
# This isn't efficient, but easy for now
|
# This isn't efficient, but easy for now
|
||||||
if module:
|
if not gds_filename:
|
||||||
gds_name = OPTS.openram_temp+"temp.gds"
|
gds_filename = OPTS.openram_temp+"temp.gds"
|
||||||
module.gds_write(gds_name)
|
self.cell.gds_write(gds_filename)
|
||||||
|
|
||||||
# Load the gds file and read in all the shapes
|
# Load the gds file and read in all the shapes
|
||||||
self.layout = gdsMill.VlsiLayout(units=tech.GDS["unit"])
|
self.layout = gdsMill.VlsiLayout(units=tech.GDS["unit"])
|
||||||
self.reader = gdsMill.Gds2reader(self.layout)
|
self.reader = gdsMill.Gds2reader(self.layout)
|
||||||
self.reader.loadFromFile(gds_name)
|
self.reader.loadFromFile(gds_filename)
|
||||||
self.top_name = self.layout.rootStructureName
|
self.top_name = self.layout.rootStructureName
|
||||||
|
|
||||||
|
# Set up layers and track sizes
|
||||||
|
self.set_layers(layers)
|
||||||
|
|
||||||
### The pin data structures
|
### The pin data structures
|
||||||
# A map of pin names to pin structures
|
# A map of pin names to pin structures
|
||||||
self.pins = {}
|
self.pins = {}
|
||||||
|
|
@ -157,6 +159,7 @@ class router:
|
||||||
self.pins[pin_name] = pin_set
|
self.pins[pin_name] = pin_set
|
||||||
self.all_pins.update(pin_set)
|
self.all_pins.update(pin_set)
|
||||||
|
|
||||||
|
|
||||||
def find_pins(self,pin_name):
|
def find_pins(self,pin_name):
|
||||||
"""
|
"""
|
||||||
Finds the pin shapes and converts to tracks.
|
Finds the pin shapes and converts to tracks.
|
||||||
|
|
@ -189,7 +192,53 @@ class router:
|
||||||
# # self.rg.reinit()
|
# # self.rg.reinit()
|
||||||
|
|
||||||
|
|
||||||
|
def find_pins_and_blockages(self, pin_list):
|
||||||
|
"""
|
||||||
|
Find the pins and blockages in the design
|
||||||
|
"""
|
||||||
|
# This finds the pin shapes and sorts them into "groups" that are connected
|
||||||
|
for pin in pin_list:
|
||||||
|
self.find_pins(pin)
|
||||||
|
|
||||||
|
# This will get all shapes as blockages and convert to grid units
|
||||||
|
# This ignores shapes that were pins
|
||||||
|
self.find_blockages()
|
||||||
|
|
||||||
|
# This will convert the pins to grid units
|
||||||
|
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
|
||||||
|
for pin in pin_list:
|
||||||
|
self.convert_pins(pin)
|
||||||
|
|
||||||
|
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
|
||||||
|
self.enclose_pins()
|
||||||
|
|
||||||
|
def prepare_blockages(self):
|
||||||
|
"""
|
||||||
|
Reset and add all of the blockages in the design.
|
||||||
|
Names is a list of pins to add as a blockage.
|
||||||
|
"""
|
||||||
|
debug.info(1,"Preparing blockages.")
|
||||||
|
|
||||||
|
# Start fresh. Not the best for run-time, but simpler.
|
||||||
|
self.clear_blockages()
|
||||||
|
# This adds the initial blockges of the design
|
||||||
|
#print("BLOCKING:",self.blocked_grids)
|
||||||
|
self.set_blockages(self.blocked_grids,True)
|
||||||
|
|
||||||
|
# Block all of the supply rails (some will be unblocked if they're a target)
|
||||||
|
self.set_supply_rail_blocked(True)
|
||||||
|
|
||||||
|
# Block all of the pin components (some will be unblocked if they're a source/target)
|
||||||
|
for name in self.pin_components.keys():
|
||||||
|
self.set_blockages(self.pin_components[name],True)
|
||||||
|
|
||||||
|
# Block all of the pin component partial blockages
|
||||||
|
for name in self.pin_component_blockages.keys():
|
||||||
|
self.set_blockages(self.pin_component_blockages[name],True)
|
||||||
|
|
||||||
|
# These are the paths that have already been routed.
|
||||||
|
self.set_path_blockages()
|
||||||
|
|
||||||
def translate_coordinates(self, coord, mirr, angle, xyShift):
|
def translate_coordinates(self, coord, mirr, angle, xyShift):
|
||||||
"""
|
"""
|
||||||
Calculate coordinates after flip, rotate, and shift
|
Calculate coordinates after flip, rotate, and shift
|
||||||
|
|
@ -251,6 +300,7 @@ class router:
|
||||||
"""
|
"""
|
||||||
Clear all blockages on the grid.
|
Clear all blockages on the grid.
|
||||||
"""
|
"""
|
||||||
|
debug.info(2,"Clearing all blockages")
|
||||||
self.rg.clear_blockages()
|
self.rg.clear_blockages()
|
||||||
|
|
||||||
def set_blockages(self, blockages, value=True):
|
def set_blockages(self, blockages, value=True):
|
||||||
|
|
@ -776,6 +826,7 @@ class router:
|
||||||
# FIXME: This could be optimized, but we just do a simple greedy biggest shape
|
# FIXME: This could be optimized, but we just do a simple greedy biggest shape
|
||||||
# for now.
|
# for now.
|
||||||
for pin_name in self.pin_components.keys():
|
for pin_name in self.pin_components.keys():
|
||||||
|
print("Enclosing {}".format(pin_name))
|
||||||
for pin_set,partial_set in zip(self.pin_components[pin_name],self.pin_component_blockages[pin_name]):
|
for pin_set,partial_set in zip(self.pin_components[pin_name],self.pin_component_blockages[pin_name]):
|
||||||
total_pin_grids = pin_set | partial_set
|
total_pin_grids = pin_set | partial_set
|
||||||
while self.enclose_pin_grids(total_pin_grids):
|
while self.enclose_pin_grids(total_pin_grids):
|
||||||
|
|
@ -834,6 +885,7 @@ class router:
|
||||||
"""
|
"""
|
||||||
Add the supply rails of given name as a routing target.
|
Add the supply rails of given name as a routing target.
|
||||||
"""
|
"""
|
||||||
|
debug.info(2,"Add supply rail target {}".format(pin_name))
|
||||||
for rail in self.supply_rails:
|
for rail in self.supply_rails:
|
||||||
if rail.name != pin_name:
|
if rail.name != pin_name:
|
||||||
continue
|
continue
|
||||||
|
|
@ -847,6 +899,7 @@ class router:
|
||||||
"""
|
"""
|
||||||
Add the supply rails of given name as a routing target.
|
Add the supply rails of given name as a routing target.
|
||||||
"""
|
"""
|
||||||
|
debug.info(2,"Blocking supply rail")
|
||||||
for rail in self.supply_rails:
|
for rail in self.supply_rails:
|
||||||
for wave_index in range(len(rail)):
|
for wave_index in range(len(rail)):
|
||||||
pin_in_tracks = rail[wave_index]
|
pin_in_tracks = rail[wave_index]
|
||||||
|
|
@ -857,6 +910,7 @@ class router:
|
||||||
"""
|
"""
|
||||||
Block all of the pin components.
|
Block all of the pin components.
|
||||||
"""
|
"""
|
||||||
|
debug.info(2,"Setting blockages {0} {1}".format(pin_name,value))
|
||||||
for component in self.pin_components[pin_name]:
|
for component in self.pin_components[pin_name]:
|
||||||
self.set_blockages(component, value)
|
self.set_blockages(component, value)
|
||||||
|
|
||||||
|
|
@ -892,15 +946,16 @@ class router:
|
||||||
"""
|
"""
|
||||||
path=self.prepare_path(path)
|
path=self.prepare_path(path)
|
||||||
|
|
||||||
# convert the path back to absolute units from tracks
|
debug.info(1,"Adding route: {}".format(str(path)))
|
||||||
# This assumes 1-track wide again
|
|
||||||
abs_path = [self.convert_point_to_units(x[0]) for x in path]
|
|
||||||
debug.info(1,str(abs_path))
|
|
||||||
|
|
||||||
# If it is only a square, add an enclosure to the track
|
# If it is only a square, add an enclosure to the track
|
||||||
if len(path)==1:
|
if len(path)==1:
|
||||||
self.add_single_enclosure(abs_path[0])
|
print("Single {}".format(str(path[0][0])))
|
||||||
|
self.add_single_enclosure(path[0][0])
|
||||||
else:
|
else:
|
||||||
|
print("Route")
|
||||||
|
# convert the path back to absolute units from tracks
|
||||||
|
# This assumes 1-track wide again
|
||||||
|
abs_path = [self.convert_point_to_units(x[0]) for x in path]
|
||||||
# Otherwise, add the route which includes enclosures
|
# Otherwise, add the route which includes enclosures
|
||||||
self.cell.add_route(layers=self.layers,
|
self.cell.add_route(layers=self.layers,
|
||||||
coordinates=abs_path,
|
coordinates=abs_path,
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,12 @@ class signal_router(router):
|
||||||
route on a given layer. This is limited to two layer routes.
|
route on a given layer. This is limited to two layer routes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, gds_name=None, module=None):
|
def __init__(self, layers, design, gds_filename=None):
|
||||||
"""
|
"""
|
||||||
Use the gds file for the blockages with the top module topName and
|
This will route on layers in design. It will get the blockages from
|
||||||
layers for the layers to route on
|
either the gds file name or the design itself (by saving to a gds file).
|
||||||
"""
|
"""
|
||||||
router.__init__(self, gds_name, module)
|
router.__init__(self, layers, design, gds_filename)
|
||||||
|
|
||||||
|
|
||||||
def create_routing_grid(self):
|
def create_routing_grid(self):
|
||||||
|
|
@ -36,14 +36,13 @@ class signal_router(router):
|
||||||
self.rg = signal_grid.signal_grid(self.ll, self.ur, self.track_width)
|
self.rg = signal_grid.signal_grid(self.ll, self.ur, self.track_width)
|
||||||
|
|
||||||
|
|
||||||
def route(self, cell, layers, src, dest, detour_scale=5):
|
def route(self, src, dest, detour_scale=5):
|
||||||
"""
|
"""
|
||||||
Route a single source-destination net and return
|
Route a single source-destination net and return
|
||||||
the simplified rectilinear path. Cost factor is how sub-optimal to explore for a feasible route.
|
the simplified rectilinear path. Cost factor is how sub-optimal to explore for a feasible route.
|
||||||
This is used to speed up the routing when there is not much detouring needed.
|
This is used to speed up the routing when there is not much detouring needed.
|
||||||
"""
|
"""
|
||||||
debug.info(1,"Running signal router from {0} to {1}...".format(src,dest))
|
debug.info(1,"Running signal router from {0} to {1}...".format(src,dest))
|
||||||
self.cell = cell
|
|
||||||
|
|
||||||
self.pins[src] = []
|
self.pins[src] = []
|
||||||
self.pins[dest] = []
|
self.pins[dest] = []
|
||||||
|
|
@ -52,38 +51,29 @@ class signal_router(router):
|
||||||
if (hasattr(self,'rg')):
|
if (hasattr(self,'rg')):
|
||||||
self.clear_pins()
|
self.clear_pins()
|
||||||
else:
|
else:
|
||||||
# Set up layers and track sizes
|
|
||||||
self.set_layers(layers)
|
|
||||||
# Creat a routing grid over the entire area
|
# Creat a routing grid over the entire area
|
||||||
# FIXME: This could be created only over the routing region,
|
# FIXME: This could be created only over the routing region,
|
||||||
# but this is simplest for now.
|
# but this is simplest for now.
|
||||||
self.create_routing_grid()
|
self.create_routing_grid()
|
||||||
|
|
||||||
# Now add the blockages (all shapes except the pins)
|
# Get the pin shapes
|
||||||
self.find_pins(src)
|
self.find_pins_and_blockages([src, dest])
|
||||||
self.find_pins(dest)
|
|
||||||
|
|
||||||
# This will get all shapes as blockages
|
# Block everything
|
||||||
self.find_blockages()
|
self.prepare_blockages()
|
||||||
|
# Clear the pins we are routing
|
||||||
# Now add the blockages
|
self.set_blockages(self.pin_components[src],False)
|
||||||
self.set_blockages(self.blocked_grids,True)
|
self.set_blockages(self.pin_components[dest],False)
|
||||||
#self.set_blockages(self.pin_partials[src],True)
|
|
||||||
#self.set_blockages(self.pin_partials[dest],True)
|
|
||||||
|
|
||||||
# Add blockages from previous paths
|
|
||||||
self.set_path_blockages()
|
|
||||||
|
|
||||||
|
|
||||||
# Now add the src/tgt if they are not blocked by other shapes
|
# Now add the src/tgt if they are not blocked by other shapes
|
||||||
self.add_source(src)
|
self.add_source(src)
|
||||||
self.add_target(dest)
|
self.add_target(dest)
|
||||||
|
|
||||||
if not self.run_router(detour_scale):
|
if not self.run_router(detour_scale=detour_scale):
|
||||||
|
self.write_debug_gds(stop_program=False)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.write_debug_gds()
|
self.write_debug_gds(stop_program=False)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,13 @@ class supply_router(router):
|
||||||
routes a grid to connect the supply on the two layers.
|
routes a grid to connect the supply on the two layers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, gds_name=None, module=None):
|
def __init__(self, layers, design, gds_filename=None):
|
||||||
"""
|
"""
|
||||||
Use the gds file for the blockages with the top module topName and
|
This will route on layers in design. It will get the blockages from
|
||||||
layers for the layers to route on
|
either the gds file name or the design itself (by saving to a gds file).
|
||||||
"""
|
"""
|
||||||
router.__init__(self, gds_name, module)
|
router.__init__(self, layers, design, gds_filename)
|
||||||
|
|
||||||
# Power rail width in grid units.
|
# Power rail width in grid units.
|
||||||
self.rail_track_width = 2
|
self.rail_track_width = 2
|
||||||
|
|
||||||
|
|
@ -38,12 +38,11 @@ class supply_router(router):
|
||||||
import supply_grid
|
import supply_grid
|
||||||
self.rg = supply_grid.supply_grid(self.ll, self.ur, self.track_width)
|
self.rg = supply_grid.supply_grid(self.ll, self.ur, self.track_width)
|
||||||
|
|
||||||
def route(self, cell, layers, vdd_name="vdd", gnd_name="gnd"):
|
def route(self, vdd_name="vdd", gnd_name="gnd"):
|
||||||
"""
|
"""
|
||||||
Add power supply rails and connect all pins to these rails.
|
Add power supply rails and connect all pins to these rails.
|
||||||
"""
|
"""
|
||||||
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
|
debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name))
|
||||||
self.cell = cell
|
|
||||||
self.vdd_name = vdd_name
|
self.vdd_name = vdd_name
|
||||||
self.gnd_name = gnd_name
|
self.gnd_name = gnd_name
|
||||||
|
|
||||||
|
|
@ -51,15 +50,13 @@ class supply_router(router):
|
||||||
if (hasattr(self,'rg')):
|
if (hasattr(self,'rg')):
|
||||||
self.clear_pins()
|
self.clear_pins()
|
||||||
else:
|
else:
|
||||||
# Set up layers and track sizes
|
|
||||||
self.set_layers(layers)
|
|
||||||
# Creat a routing grid over the entire area
|
# Creat a routing grid over the entire area
|
||||||
# FIXME: This could be created only over the routing region,
|
# FIXME: This could be created only over the routing region,
|
||||||
# but this is simplest for now.
|
# but this is simplest for now.
|
||||||
self.create_routing_grid()
|
self.create_routing_grid()
|
||||||
|
|
||||||
# Get the pin shapes
|
# Get the pin shapes
|
||||||
self.find_pins_and_blockages()
|
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
|
||||||
|
|
||||||
# Add the supply rails in a mesh network and connect H/V with vias
|
# Add the supply rails in a mesh network and connect H/V with vias
|
||||||
# Block everything
|
# Block everything
|
||||||
|
|
@ -84,51 +81,6 @@ class supply_router(router):
|
||||||
self.write_debug_gds(stop_program=False)
|
self.write_debug_gds(stop_program=False)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def find_pins_and_blockages(self):
|
|
||||||
"""
|
|
||||||
Find the pins and blockages in teh design
|
|
||||||
"""
|
|
||||||
# This finds the pin shapes and sorts them into "groups" that are connected
|
|
||||||
self.find_pins(self.vdd_name)
|
|
||||||
self.find_pins(self.gnd_name)
|
|
||||||
|
|
||||||
# This will get all shapes as blockages and convert to grid units
|
|
||||||
# This ignores shapes that were pins
|
|
||||||
self.find_blockages()
|
|
||||||
|
|
||||||
# This will convert the pins to grid units
|
|
||||||
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
|
|
||||||
self.convert_pins(self.vdd_name)
|
|
||||||
self.convert_pins(self.gnd_name)
|
|
||||||
|
|
||||||
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
|
|
||||||
self.enclose_pins()
|
|
||||||
|
|
||||||
|
|
||||||
def prepare_blockages(self):
|
|
||||||
"""
|
|
||||||
Reset and add all of the blockages in the design.
|
|
||||||
Names is a list of pins to add as a blockage.
|
|
||||||
"""
|
|
||||||
# Start fresh. Not the best for run-time, but simpler.
|
|
||||||
self.clear_blockages()
|
|
||||||
# This adds the initial blockges of the design
|
|
||||||
#print("BLOCKING:",self.blocked_grids)
|
|
||||||
self.set_blockages(self.blocked_grids,True)
|
|
||||||
|
|
||||||
# Block all of the supply rails (some will be unblocked if they're a target)
|
|
||||||
self.set_supply_rail_blocked(True)
|
|
||||||
|
|
||||||
# Block all of the pin components (some will be unblocked if they're a source/target)
|
|
||||||
for name in self.pin_components.keys():
|
|
||||||
self.set_blockages(self.pin_components[name],True)
|
|
||||||
|
|
||||||
# Block all of the pin component partial blockages
|
|
||||||
for name in self.pin_component_blockages.keys():
|
|
||||||
self.set_blockages(self.pin_component_blockages[name],True)
|
|
||||||
|
|
||||||
# These are the paths that have already been routed.
|
|
||||||
self.set_path_blockages()
|
|
||||||
|
|
||||||
def connect_supply_rails(self, name):
|
def connect_supply_rails(self, name):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ class no_blockages_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
|
r=router(layer_stack,self,gds_file)
|
||||||
|
self.assertTrue(r.route(src="A",dest="B"))
|
||||||
|
|
||||||
r=routing("01_no_blockages_test_{0}".format(OPTS.tech_name))
|
r=routing("01_no_blockages_test_{0}".format(OPTS.tech_name))
|
||||||
self.local_drc_check(r)
|
self.local_drc_check(r)
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ class blockages_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
|
r=router(layer_stack,self,gds_file)
|
||||||
|
self.assertTrue(r.route(src="A",dest="B"))
|
||||||
|
|
||||||
r=routing("02_blockages_test_{0}".format(OPTS.tech_name))
|
r=routing("02_blockages_test_{0}".format(OPTS.tech_name))
|
||||||
self.local_drc_check(r)
|
self.local_drc_check(r)
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ class same_layer_pins_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
|
r=router(layer_stack,self,gds_file)
|
||||||
|
self.assertTrue(r.route(src="A",dest="B"))
|
||||||
|
|
||||||
r = routing("03_same_layer_pins_test_{0}".format(OPTS.tech_name))
|
r = routing("03_same_layer_pins_test_{0}".format(OPTS.tech_name))
|
||||||
self.local_drc_check(r)
|
self.local_drc_check(r)
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ class diff_layer_pins_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
|
r=router(layer_stack,self,gds_file)
|
||||||
|
self.assertTrue(r.route(src="A",dest="B"))
|
||||||
|
|
||||||
r = routing("04_diff_layer_pins_test_{0}".format(OPTS.tech_name))
|
r = routing("04_diff_layer_pins_test_{0}".format(OPTS.tech_name))
|
||||||
self.local_drc_check(r)
|
self.local_drc_check(r)
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,10 @@ class two_nets_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
self.assertTrue(r.route(self,layer_stack,src="A",dest="B"))
|
r=router(layer_stack,self,gds_file)
|
||||||
self.assertTrue(r.route(self,layer_stack,src="C",dest="D"))
|
self.assertTrue(r.route(src="A",dest="B"))
|
||||||
|
self.assertTrue(r.route(src="C",dest="D"))
|
||||||
|
|
||||||
r = routing("05_two_nets_test_{0}".format(OPTS.tech_name))
|
r = routing("05_two_nets_test_{0}".format(OPTS.tech_name))
|
||||||
self.local_drc_check(r)
|
self.local_drc_check(r)
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,13 @@ class pin_location_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
|
r=router(layer_stack,self,gds_file)
|
||||||
# these are user coordinates and layers
|
# these are user coordinates and layers
|
||||||
src_pin = [[0.52, 4.099],11]
|
src_pin = [[0.52, 4.099],11]
|
||||||
tgt_pin = [[3.533, 1.087],11]
|
tgt_pin = [[3.533, 1.087],11]
|
||||||
#r.route(layer_stack,src="A",dest="B")
|
#r.route(layer_stack,src="A",dest="B")
|
||||||
self.assertTrue(r.route(self,layer_stack,src=src_pin,dest=tgt_pin))
|
self.assertTrue(r.route(src=src_pin,dest=tgt_pin))
|
||||||
|
|
||||||
# This only works for freepdk45 since the coordinates are hard coded
|
# This only works for freepdk45 since the coordinates are hard coded
|
||||||
if OPTS.tech_name == "freepdk45":
|
if OPTS.tech_name == "freepdk45":
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ class big_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
|
r=router(layer_stack,self,gds_file)
|
||||||
connections=[('out_0_2', 'a_0_0'),
|
connections=[('out_0_2', 'a_0_0'),
|
||||||
('out_0_3', 'b_0_0'),
|
('out_0_3', 'b_0_0'),
|
||||||
('out_0_0', 'a_0_1'),
|
('out_0_0', 'a_0_1'),
|
||||||
|
|
@ -61,7 +61,7 @@ class big_test(openram_test):
|
||||||
('out_4_1', 'a_4_3'),
|
('out_4_1', 'a_4_3'),
|
||||||
('out_4_5', 'b_4_3')]
|
('out_4_5', 'b_4_3')]
|
||||||
for (src,tgt) in connections:
|
for (src,tgt) in connections:
|
||||||
self.assertTrue(r.route(self,layer_stack,src=src,dest=tgt))
|
self.assertTrue(r.route(src=src,dest=tgt))
|
||||||
|
|
||||||
# This test only runs on scn3me_subm tech
|
# This test only runs on scn3me_subm tech
|
||||||
if OPTS.tech_name=="scn3me_subm":
|
if OPTS.tech_name=="scn3me_subm":
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,12 @@ class expand_region_test(openram_test):
|
||||||
offset=[0,0])
|
offset=[0,0])
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
r=router(gds_file)
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
layer_stack =("metal1","via1","metal2")
|
||||||
|
r=router(layer_stack,self,gds_file)
|
||||||
# This should be infeasible because it is blocked without a detour.
|
# This should be infeasible because it is blocked without a detour.
|
||||||
self.assertFalse(r.route(self,layer_stack,src="A",dest="B",detour_scale=1))
|
self.assertFalse(r.route(src="A",dest="B",detour_scale=1))
|
||||||
# This should be feasible because we allow it to detour
|
# This should be feasible because we allow it to detour
|
||||||
self.assertTrue(r.route(self,layer_stack,src="A",dest="B",detour_scale=3))
|
self.assertTrue(r.route(src="A",dest="B",detour_scale=3))
|
||||||
|
|
||||||
r = routing("08_expand_region_test_{0}".format(OPTS.tech_name))
|
r = routing("08_expand_region_test_{0}".format(OPTS.tech_name))
|
||||||
self.local_drc_check(r)
|
self.local_drc_check(r)
|
||||||
|
|
|
||||||
|
|
@ -17,36 +17,26 @@ class no_blockages_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
globals.init_openram("config_{0}".format(OPTS.tech_name))
|
globals.init_openram("config_{0}".format(OPTS.tech_name))
|
||||||
from gds_cell import gds_cell
|
|
||||||
from design import design
|
|
||||||
from supply_router import supply_router as router
|
from supply_router import supply_router as router
|
||||||
|
|
||||||
class routing(design, openram_test):
|
if True:
|
||||||
"""
|
from control_logic import control_logic
|
||||||
A generic GDS design that we can route on.
|
cell = control_logic(16)
|
||||||
"""
|
else:
|
||||||
def __init__(self, name):
|
from sram import sram
|
||||||
design.__init__(self, "top")
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=4,
|
||||||
# Instantiate a GDS cell with the design
|
num_words=16,
|
||||||
globals.setup_paths()
|
num_banks=1)
|
||||||
from control_logic import control_logic
|
|
||||||
cell = control_logic(16)
|
c.words_per_row=1
|
||||||
#from pinv import pinv
|
cell = sram(c, "sram1")
|
||||||
#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(cell.pin_map.keys())
|
|
||||||
|
|
||||||
r=router(module=cell)
|
print("PRE:",cell)
|
||||||
layer_stack =("metal3","via3","metal4")
|
layer_stack =("metal3","via3","metal4")
|
||||||
self.assertTrue(r.route(self,layer_stack))
|
rtr=router(layer_stack, cell)
|
||||||
|
self.assertTrue(rtr.route())
|
||||||
r=routing("10_supply_grid_test_{0}".format(OPTS.tech_name))
|
self.local_check(cell,True)
|
||||||
self.local_drc_check(r)
|
|
||||||
|
|
||||||
# fails if there are any DRC errors on any cells
|
# fails if there are any DRC errors on any cells
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue