2020-12-23 00:56:51 +01:00
|
|
|
# See LICENSE for licensing information.
|
|
|
|
|
#
|
|
|
|
|
# Copyright (c) 2016-2019 Regents of the University of California and The Board
|
|
|
|
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
|
|
|
|
# (acting for and on behalf of Oklahoma State University)
|
|
|
|
|
# All rights reserved.
|
|
|
|
|
#
|
|
|
|
|
import debug
|
|
|
|
|
from globals import print_time
|
|
|
|
|
from router import router
|
|
|
|
|
from datetime import datetime
|
2021-01-06 18:40:32 +01:00
|
|
|
from signal_grid import signal_grid
|
2020-12-23 00:56:51 +01:00
|
|
|
|
2020-12-23 01:35:05 +01:00
|
|
|
|
|
|
|
|
class signal_escape_router(router):
|
2020-12-23 00:56:51 +01:00
|
|
|
"""
|
|
|
|
|
A router that routes signals to perimeter and makes pins.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, layers, design, gds_filename=None):
|
|
|
|
|
"""
|
|
|
|
|
This will route on layers in design. It will get the blockages from
|
|
|
|
|
either the gds file name or the design itself (by saving to a gds file).
|
|
|
|
|
"""
|
|
|
|
|
router.__init__(self, layers, design, gds_filename, 1)
|
|
|
|
|
|
|
|
|
|
def create_routing_grid(self):
|
|
|
|
|
"""
|
|
|
|
|
Create a sprase routing grid with A* expansion functions.
|
|
|
|
|
"""
|
|
|
|
|
size = self.ur - self.ll
|
|
|
|
|
debug.info(1,"Size: {0} x {1}".format(size.x, size.y))
|
2021-01-06 18:40:32 +01:00
|
|
|
self.rg = signal_grid(self.ll, self.ur, self.track_width)
|
2020-12-23 00:56:51 +01:00
|
|
|
|
2021-01-06 18:40:32 +01:00
|
|
|
def escape_route(self, pin_names):
|
2020-12-23 00:56:51 +01:00
|
|
|
"""
|
|
|
|
|
Takes a list of tuples (name, side) and routes them. After routing,
|
|
|
|
|
it removes the old pin and places a new one on the perimeter.
|
|
|
|
|
"""
|
2021-01-06 18:40:32 +01:00
|
|
|
self.create_routing_grid()
|
2020-12-23 00:56:51 +01:00
|
|
|
|
|
|
|
|
start_time = datetime.now()
|
|
|
|
|
self.find_pins_and_blockages(pin_names)
|
|
|
|
|
print_time("Finding pins and blockages",datetime.now(), start_time, 3)
|
|
|
|
|
|
|
|
|
|
# Route the supply pins to the supply rails
|
|
|
|
|
# Route vdd first since we want it to be shorter
|
|
|
|
|
start_time = datetime.now()
|
2021-01-06 18:40:32 +01:00
|
|
|
for pin_name in pin_names:
|
|
|
|
|
self.route_signal(pin_name)
|
2020-12-23 00:56:51 +01:00
|
|
|
|
|
|
|
|
print_time("Maze routing pins",datetime.now(), start_time, 3)
|
|
|
|
|
|
2020-12-23 19:49:47 +01:00
|
|
|
# self.write_debug_gds("final_escape_router.gds",False)
|
|
|
|
|
|
2020-12-23 00:56:51 +01:00
|
|
|
return True
|
|
|
|
|
|
2021-01-06 18:40:32 +01:00
|
|
|
def route_signal(self, pin_name, side="all"):
|
2020-12-23 00:56:51 +01:00
|
|
|
|
|
|
|
|
for detour_scale in [5 * pow(2, x) for x in range(5)]:
|
2021-01-04 20:52:02 +01:00
|
|
|
debug.info(1, "Escape routing {0} with scale {1}".format(pin_name, detour_scale))
|
2020-12-23 00:56:51 +01:00
|
|
|
|
|
|
|
|
# Clear everything in the routing grid.
|
|
|
|
|
self.rg.reinit()
|
|
|
|
|
|
|
|
|
|
# This is inefficient since it is non-incremental, but it was
|
|
|
|
|
# easier to debug.
|
|
|
|
|
self.prepare_blockages(pin_name)
|
|
|
|
|
|
|
|
|
|
# Add the single component of the pin as the source
|
|
|
|
|
# which unmarks it as a blockage too
|
|
|
|
|
self.add_source(pin_name)
|
|
|
|
|
|
|
|
|
|
# Marks the grid cells all along the perimeter as a target
|
|
|
|
|
self.add_perimeter_target(side)
|
|
|
|
|
|
|
|
|
|
# Actually run the A* router
|
|
|
|
|
if self.run_router(detour_scale=detour_scale):
|
|
|
|
|
new_pin = self.get_perimeter_pin()
|
|
|
|
|
self.cell.replace_layout_pin(pin_name, new_pin)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.write_debug_gds("debug_route.gds", True)
|
|
|
|
|
|
|
|
|
|
|