mirror of https://github.com/VLSIDA/OpenRAM.git
Contract path to simplified route
This commit is contained in:
parent
aa950c3b21
commit
0a9b326f6a
|
|
@ -244,12 +244,9 @@ class layout:
|
||||||
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)
|
||||||
# TODO: parse the width/height
|
|
||||||
# TODO: parse the pin locations
|
|
||||||
else:
|
else:
|
||||||
debug.info(3, "creating structure %s" % self.name)
|
debug.info(3, "creating structure %s" % self.name)
|
||||||
self.gds = gdsMill.VlsiLayout(
|
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
|
||||||
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 """
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class cell:
|
||||||
b+=b1
|
b+=b1
|
||||||
count+=1
|
count+=1
|
||||||
|
|
||||||
if self.source or self.target:
|
if self.source or self.target:
|
||||||
[r1,g1,b1] = ImageColor.getrgb("Red")
|
[r1,g1,b1] = ImageColor.getrgb("Red")
|
||||||
r+=r1
|
r+=r1
|
||||||
g+=g1
|
g+=g1
|
||||||
|
|
|
||||||
|
|
@ -154,11 +154,12 @@ class grid:
|
||||||
"""
|
"""
|
||||||
# expand from the last point
|
# expand from the last point
|
||||||
point = path[-1]
|
point = path[-1]
|
||||||
|
|
||||||
neighbors = []
|
neighbors = []
|
||||||
# check z layer for enforced direction routing
|
# check z layer for enforced direction routing
|
||||||
if point.z==0:
|
if point.z==0:
|
||||||
east = point + vector3d(1,0,0)
|
east = point + vector3d(1,0,0)
|
||||||
west= point + vector3d(-11,0,0)
|
west= point + vector3d(-1,0,0)
|
||||||
if east.x<self.width and not self.map[east].blocked and not self.map[east].visited:
|
if east.x<self.width and not self.map[east].blocked and not self.map[east].visited:
|
||||||
neighbors.append(east)
|
neighbors.append(east)
|
||||||
if west.x>=0 and not self.map[west].blocked and not self.map[west].visited:
|
if west.x>=0 and not self.map[west].blocked and not self.map[west].visited:
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,6 @@ class router:
|
||||||
self.track_width = max(self.horiz_track_width,self.vert_track_width)
|
self.track_width = max(self.horiz_track_width,self.vert_track_width)
|
||||||
print "Track width:",self.track_width
|
print "Track width:",self.track_width
|
||||||
|
|
||||||
# to scale coordinates to tracks
|
|
||||||
self.track_factor = [1/self.track_width] * 2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_routing_grid(self):
|
def create_routing_grid(self):
|
||||||
|
|
@ -117,15 +114,16 @@ class router:
|
||||||
self.set_source(src)
|
self.set_source(src)
|
||||||
self.set_target(dest)
|
self.set_target(dest)
|
||||||
self.find_blockages()
|
self.find_blockages()
|
||||||
|
# returns the path in tracks
|
||||||
path = self.rg.route()
|
path = self.rg.route()
|
||||||
debug.info(0,"Found path. ")
|
debug.info(0,"Found path. ")
|
||||||
debug.info(2,str(path))
|
debug.info(2,str(path))
|
||||||
return path
|
self.set_path(path)
|
||||||
|
# convert the path back to absolute units from tracks
|
||||||
|
abs_path = self.convert_path_to_units(path)
|
||||||
|
debug.info(2,str(abs_path))
|
||||||
|
return abs_path
|
||||||
|
|
||||||
def add_route(self,start, end, layerstack):
|
|
||||||
""" Add a wire route from the start to the end point"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def create_steiner_routes(self,pins):
|
def create_steiner_routes(self,pins):
|
||||||
"""Find a set of steiner points and then return the list of
|
"""Find a set of steiner points and then return the list of
|
||||||
point-to-point routes."""
|
point-to-point routes."""
|
||||||
|
|
@ -163,6 +161,41 @@ class router:
|
||||||
coordinate += [vector(maxx, maxy)]
|
coordinate += [vector(maxx, maxy)]
|
||||||
return coordinate
|
return coordinate
|
||||||
|
|
||||||
|
def get_inertia(self,p0,p1):
|
||||||
|
# direction (index) of movement
|
||||||
|
if p0.x==p1.x:
|
||||||
|
inertia = 1
|
||||||
|
elif p0.y==p1.y:
|
||||||
|
inertia = 0
|
||||||
|
else:
|
||||||
|
inertia = 2
|
||||||
|
return inertia
|
||||||
|
|
||||||
|
def contract_path(self,path):
|
||||||
|
"""
|
||||||
|
Remove intermediate points in a rectilinear path.
|
||||||
|
"""
|
||||||
|
debug.info(0,"Initial path:"+str(path))
|
||||||
|
newpath = [path[0]]
|
||||||
|
for i in range(len(path)-1):
|
||||||
|
if i==0:
|
||||||
|
continue
|
||||||
|
prev_inertia=self.get_inertia(path[i-1],path[i])
|
||||||
|
next_inertia=self.get_inertia(path[i],path[i+1])
|
||||||
|
|
||||||
|
if prev_inertia!=next_inertia:
|
||||||
|
newpath.append(path[i])
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
newpath.append(path[-1])
|
||||||
|
debug.info(0,"Final path:"+str(newpath))
|
||||||
|
return newpath
|
||||||
|
|
||||||
|
def set_path(self,path):
|
||||||
|
debug.info(2,"Set path: " + str(path))
|
||||||
|
self.rg.set_path(path)
|
||||||
|
|
||||||
def set_source(self,name):
|
def set_source(self,name):
|
||||||
shape = self.find_pin(name)
|
shape = self.find_pin(name)
|
||||||
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
zindex = 0 if self.pin_layers[name]==self.horiz_layer_number else 1
|
||||||
|
|
@ -215,6 +248,24 @@ class router:
|
||||||
|
|
||||||
self.write_obstacle(cur_sref.sName, sMirr, sAngle, sxyShift)
|
self.write_obstacle(cur_sref.sName, sMirr, sAngle, sxyShift)
|
||||||
|
|
||||||
|
def convert_path_to_units(self,path):
|
||||||
|
"""
|
||||||
|
Convert a path set of tracks to center line path.
|
||||||
|
"""
|
||||||
|
# First, simplify the path.
|
||||||
|
path = self.contract_path(path)
|
||||||
|
|
||||||
|
newpath = []
|
||||||
|
track_factor = [self.track_width] * 2
|
||||||
|
for p in path:
|
||||||
|
# we can ignore the layers here
|
||||||
|
# add_wire will filter out duplicates
|
||||||
|
pt = vector(p[0],p[1])
|
||||||
|
pt=pt.scale(track_factor)
|
||||||
|
pt=snap_to_grid(pt+self.offset)
|
||||||
|
newpath.append(pt)
|
||||||
|
return newpath
|
||||||
|
|
||||||
def convert_to_tracks(self,shape,round_bigger=True):
|
def convert_to_tracks(self,shape,round_bigger=True):
|
||||||
"""
|
"""
|
||||||
Convert a rectangular shape into track units.
|
Convert a rectangular shape into track units.
|
||||||
|
|
@ -225,14 +276,18 @@ class router:
|
||||||
ll = snap_to_grid(ll-self.offset)
|
ll = snap_to_grid(ll-self.offset)
|
||||||
ur = snap_to_grid(ur-self.offset)
|
ur = snap_to_grid(ur-self.offset)
|
||||||
|
|
||||||
|
# to scale coordinates to tracks
|
||||||
|
track_factor = [1/self.track_width] * 2
|
||||||
|
|
||||||
|
|
||||||
# Always round blockage shapes up.
|
# Always round blockage shapes up.
|
||||||
if round_bigger:
|
if round_bigger:
|
||||||
ll = ll.scale(self.track_factor).floor()
|
ll = ll.scale(track_factor).floor()
|
||||||
ur = ur.scale(self.track_factor).ceil()
|
ur = ur.scale(track_factor).ceil()
|
||||||
# Always round pin shapes down
|
# Always round pin shapes down
|
||||||
else:
|
else:
|
||||||
ll = ll.scale(self.track_factor).round()
|
ll = ll.scale(track_factor).round()
|
||||||
ur = ur.scale(self.track_factor).round()
|
ur = ur.scale(track_factor).round()
|
||||||
|
|
||||||
|
|
||||||
return [ll,ur]
|
return [ll,ur]
|
||||||
|
|
|
||||||
|
|
@ -10,46 +10,73 @@ import globals
|
||||||
import debug
|
import debug
|
||||||
import calibre
|
import calibre
|
||||||
|
|
||||||
|
|
||||||
class no_blockages_test(unittest.TestCase):
|
class no_blockages_test(unittest.TestCase):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
globals.init_openram("config_{0}".format(OPTS.tech_name))
|
globals.init_openram("config_{0}".format(OPTS.tech_name))
|
||||||
|
|
||||||
|
import design
|
||||||
import router
|
import router
|
||||||
import wire
|
|
||||||
import tech
|
|
||||||
#r=router.router("A_to_B_no_blockages.gds")
|
|
||||||
#r=router.router("A_to_B_m1m2_blockages.gds")
|
|
||||||
#r=router.router("A_to_B_m1m2_same_layer_pins.gds")
|
|
||||||
r=router.router("A_to_B_m1m2_diff_layer_pins.gds")
|
|
||||||
layer_stack =("metal1","via1","metal2")
|
|
||||||
path=r.route(layer_stack,src="A",dest="B")
|
|
||||||
|
|
||||||
# For debug, to view the result as an image
|
class gdscell(design.design):
|
||||||
r.rg.set_path(path)
|
"""
|
||||||
r.rg.view()
|
A generic GDS design that we can route on.
|
||||||
OPTS.check_lvsdrc = False
|
"""
|
||||||
|
def __init__(self, name):
|
||||||
|
#design.design.__init__(self, name)
|
||||||
|
debug.info(2, "Create {0} object".format(name))
|
||||||
|
self.name = name
|
||||||
|
self.gds_file = name + ".gds"
|
||||||
|
self.sp_file = name + ".sp"
|
||||||
|
design.hierarchy_layout.layout.__init__(self, name)
|
||||||
|
design.hierarchy_spice.spice.__init__(self, name)
|
||||||
|
|
||||||
|
class routing(design.design):
|
||||||
|
"""
|
||||||
|
A generic GDS design that we can route on.
|
||||||
|
"""
|
||||||
|
def __init__(self, name, gdsname):
|
||||||
|
design.design.__init__(self, name)
|
||||||
|
debug.info(2, "Create {0} object".format(name))
|
||||||
|
|
||||||
#w = wire.wire(layer_stack, path)
|
cell = gdscell(gdsname)
|
||||||
OPTS.check_lvsdrc = True
|
self.add_inst(name=gdsname,
|
||||||
#self.local_check(w)
|
mod=cell,
|
||||||
|
offset=[0,0])
|
||||||
|
self.connect_inst([])
|
||||||
|
|
||||||
|
r=router.router(gdsname+".gds")
|
||||||
|
layer_stack =("metal1","via1","metal2")
|
||||||
|
path=r.route(layer_stack,src="A",dest="B")
|
||||||
|
r.rg.view()
|
||||||
|
|
||||||
|
self.add_wire(layer_stack,path)
|
||||||
|
|
||||||
#drc_errors = calibre.run_drc(name, gds_name)
|
|
||||||
drc_errors = 1
|
r = routing("test1", "A_to_B_no_blockages")
|
||||||
|
self.local_check(r)
|
||||||
|
|
||||||
|
r = routing("A_to_B_m1m2_blockages")
|
||||||
|
self.local_check(r)
|
||||||
|
|
||||||
|
r = routing("A_to_B_m1m2_same_layer_pins")
|
||||||
|
self.local_check(r)
|
||||||
|
|
||||||
|
r = routing("A_to_B_m1m2_diff_layer_pins")
|
||||||
|
self.local_check(r)
|
||||||
|
|
||||||
# fails if there are any DRC errors on any cells
|
# fails if there are any DRC errors on any cells
|
||||||
self.assertEqual(drc_errors, 0)
|
self.assertEqual(drc_errors, 0)
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
||||||
|
|
||||||
|
def local_check(self, r):
|
||||||
|
|
||||||
def local_check(self, w):
|
|
||||||
tempgds = OPTS.openram_temp + "temp.gds"
|
tempgds = OPTS.openram_temp + "temp.gds"
|
||||||
w.gds_write(tempgds)
|
r.gds_write(tempgds)
|
||||||
self.assertFalse(calibre.run_drc(w.name, tempgds))
|
self.assertFalse(calibre.run_drc(r.name, tempgds))
|
||||||
os.remove(tempgds)
|
os.remove(tempgds)
|
||||||
|
assert(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
.SUBCKT cell
|
||||||
|
.ENDS cell
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
.SUBCKT cell
|
||||||
|
.ENDS cell
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
.SUBCKT cell
|
||||||
|
.ENDS cell
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
.SUBCKT cell
|
||||||
|
.ENDS cell
|
||||||
Loading…
Reference in New Issue