2016-11-17 00:02:07 +01:00
|
|
|
import numpy as np
|
2017-04-24 19:27:04 +02:00
|
|
|
import string
|
2017-04-14 22:18:35 +02:00
|
|
|
from itertools import tee
|
2016-11-17 00:02:07 +01:00
|
|
|
import debug
|
2016-11-17 01:47:31 +01:00
|
|
|
from vector3d import vector3d
|
2016-11-17 00:02:07 +01:00
|
|
|
from cell import cell
|
2017-04-24 19:27:04 +02:00
|
|
|
import os
|
|
|
|
|
|
2016-11-17 00:02:07 +01:00
|
|
|
class grid:
|
2018-08-23 00:56:19 +02:00
|
|
|
"""
|
|
|
|
|
A two layer routing map. Each cell can be blocked in the vertical
|
2016-11-17 00:02:07 +01:00
|
|
|
or horizontal layer.
|
|
|
|
|
"""
|
|
|
|
|
|
2017-04-14 22:56:09 +02:00
|
|
|
def __init__(self):
|
2018-08-23 00:56:19 +02:00
|
|
|
""" Initialize the map and define the costs. """
|
2017-04-24 19:27:04 +02:00
|
|
|
|
|
|
|
|
# costs are relative to a unit grid
|
|
|
|
|
# non-preferred cost allows an off-direction jog of 1 grid
|
|
|
|
|
# rather than 2 vias + preferred direction (cost 5)
|
|
|
|
|
self.VIA_COST = 2
|
|
|
|
|
self.NONPREFERRED_COST = 4
|
2017-06-07 19:10:18 +02:00
|
|
|
self.PREFERRED_COST = 1
|
2017-04-14 22:18:35 +02:00
|
|
|
|
2017-04-24 19:27:04 +02:00
|
|
|
# let's leave the map sparse, cells are created on demand to reduce memory
|
2017-04-14 22:56:09 +02:00
|
|
|
self.map={}
|
2016-11-17 01:47:31 +01:00
|
|
|
|
2017-06-05 23:42:56 +02:00
|
|
|
def set_blocked(self,n):
|
|
|
|
|
self.add_map(n)
|
|
|
|
|
self.map[n].blocked=True
|
|
|
|
|
|
2017-06-07 02:12:19 +02:00
|
|
|
def is_blocked(self,n):
|
|
|
|
|
self.add_map(n)
|
|
|
|
|
return self.map[n].blocked
|
|
|
|
|
|
2017-06-05 23:42:56 +02:00
|
|
|
def add_blockage_shape(self,ll,ur,z):
|
2017-04-24 19:27:04 +02:00
|
|
|
debug.info(3,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
|
2018-08-22 20:37:24 +02:00
|
|
|
|
|
|
|
|
block_list = []
|
2016-11-17 20:24:17 +01:00
|
|
|
for x in range(int(ll[0]),int(ur[0])+1):
|
|
|
|
|
for y in range(int(ll[1]),int(ur[1])+1):
|
2018-08-22 20:37:24 +02:00
|
|
|
block_list.append(vector3d(x,y,z))
|
|
|
|
|
|
|
|
|
|
self.add_blockage(block_list)
|
2017-06-05 23:42:56 +02:00
|
|
|
|
|
|
|
|
def add_blockage(self,block_list):
|
2018-08-22 20:37:24 +02:00
|
|
|
debug.info(2,"Adding blockage list={0}".format(str(block_list)))
|
2017-06-05 23:42:56 +02:00
|
|
|
for n in block_list:
|
|
|
|
|
self.set_blocked(n)
|
|
|
|
|
|
2017-04-14 22:18:35 +02:00
|
|
|
def add_map(self,p):
|
|
|
|
|
"""
|
|
|
|
|
Add a point to the map if it doesn't exist.
|
|
|
|
|
"""
|
|
|
|
|
if p not in self.map.keys():
|
|
|
|
|
self.map[p]=cell()
|
2016-11-17 01:47:31 +01:00
|
|
|
|
2018-08-23 00:56:19 +02:00
|
|
|
def add_path(self,path):
|
2017-04-24 19:27:04 +02:00
|
|
|
"""
|
2018-08-23 00:56:19 +02:00
|
|
|
Mark the path in the routing grid for visualization
|
2016-11-17 01:47:31 +01:00
|
|
|
"""
|
2018-08-23 00:56:19 +02:00
|
|
|
self.path=path
|
|
|
|
|
for p in path:
|
|
|
|
|
self.map[p].path=True
|
2017-04-14 22:18:35 +02:00
|
|
|
|
2016-11-18 18:17:59 +01:00
|
|
|
def cost(self,path):
|
|
|
|
|
"""
|
|
|
|
|
The cost of the path is the length plus a penalty for the number
|
2017-04-24 19:27:04 +02:00
|
|
|
of vias. We assume that non-preferred direction is penalized.
|
2016-11-18 18:17:59 +01:00
|
|
|
"""
|
2017-04-24 19:27:04 +02:00
|
|
|
|
2017-04-14 22:18:35 +02:00
|
|
|
# Ignore the source pin layer change, FIXME?
|
|
|
|
|
def pairwise(iterable):
|
|
|
|
|
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
|
|
|
|
|
a, b = tee(iterable)
|
|
|
|
|
next(b, None)
|
|
|
|
|
return zip(a, b)
|
2017-04-24 19:27:04 +02:00
|
|
|
|
|
|
|
|
|
2017-04-14 22:18:35 +02:00
|
|
|
plist = pairwise(path)
|
|
|
|
|
cost = 0
|
|
|
|
|
for p0,p1 in plist:
|
|
|
|
|
if p0.z != p1.z: # via
|
2017-04-14 22:56:09 +02:00
|
|
|
cost += self.VIA_COST
|
2017-04-14 22:18:35 +02:00
|
|
|
elif p0.x != p1.x: # horizontal
|
2017-06-07 19:10:18 +02:00
|
|
|
cost += self.NONPREFERRED_COST if (p0.z == 1) else self.PREFERRED_COST
|
2017-04-14 22:18:35 +02:00
|
|
|
elif p0.y != p1.y: # vertical
|
2017-06-07 19:10:18 +02:00
|
|
|
cost += self.NONPREFERRED_COST if (p0.z == 0) else self.PREFERRED_COST
|
2017-04-14 22:18:35 +02:00
|
|
|
else:
|
|
|
|
|
debug.error("Non-changing direction!")
|
2017-04-24 19:27:04 +02:00
|
|
|
|
2017-04-14 22:18:35 +02:00
|
|
|
return cost
|
2016-11-18 18:17:59 +01:00
|
|
|
|
2018-08-23 00:56:19 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|