OpenRAM/compiler/router/router_tech.py

128 lines
5.4 KiB
Python
Raw Normal View History

# See LICENSE for licensing information.
#
2019-06-14 17:43:41 +02:00
# 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.
#
from tech import drc, layer, preferred_directions
from contact import contact
from vector import vector
import debug
2018-12-03 20:09:17 +01:00
import math
class router_tech:
"""
This is a class to hold the router tech constants.
"""
def __init__(self, layers, rail_track_width):
"""
Allows us to change the layers that we are routing on. First layer
is always horizontal, middle is via, and last is always
vertical.
"""
self.layers = layers
self.rail_track_width = rail_track_width
2019-05-31 17:43:37 +02:00
if len(self.layers) == 1:
if preferred_directions[self.layers[0]] != "H":
debug.warning("Using '{}' for horizontal routing, but it " \
"prefers vertical routing".format(self.layers[0]))
2019-05-28 02:38:59 +02:00
self.horiz_layer_name = self.vert_layer_name = self.layers[0]
self.horiz_lpp = self.vert_lpp = layer[self.layers[0]]
2019-05-28 02:38:59 +02:00
(self.vert_layer_minwidth, self.vert_layer_spacing) = self.get_supply_layer_width_space(1)
(self.horiz_layer_minwidth, self.horiz_layer_spacing) = self.get_supply_layer_width_space(0)
self.horiz_track_width = self.horiz_layer_minwidth + self.horiz_layer_spacing
self.vert_track_width = self.vert_layer_minwidth + self.vert_layer_spacing
else:
(try_horiz_layer, self.via_layer_name, try_vert_layer) = self.layers
# figure out wich of the two layers prefers horizontal/vertical
# routing
if preferred_directions[try_horiz_layer] == "H" and preferred_directions[try_vert_layer] == "V":
self.horiz_layer_name = try_horiz_layer
self.vert_layer_name = try_vert_layer
else:
raise ValueError("Layer '{}' and '{}' are using the wrong " \
"preferred_directions '{}' and '{}'. Only "\
"('H', 'V') are supported")
2019-05-28 02:38:59 +02:00
via_connect = contact(self.layers, (1, 1))
max_via_size = max(via_connect.width,via_connect.height)
2018-12-03 20:09:17 +01:00
self.horiz_lpp = layer[self.horiz_layer_name]
self.vert_lpp = layer[self.vert_layer_name]
(self.vert_layer_minwidth, self.vert_layer_spacing) = self.get_supply_layer_width_space(1)
(self.horiz_layer_minwidth, self.horiz_layer_spacing) = self.get_supply_layer_width_space(0)
2019-05-28 02:38:59 +02:00
2018-12-03 20:09:17 +01:00
# For supplies, we will make the wire wider than the vias
self.vert_layer_minwidth = max(self.vert_layer_minwidth, max_via_size)
self.horiz_layer_minwidth = max(self.horiz_layer_minwidth, max_via_size)
self.horiz_track_width = self.horiz_layer_minwidth + self.horiz_layer_spacing
self.vert_track_width = self.vert_layer_minwidth + self.vert_layer_spacing
# We'll keep horizontal and vertical tracks the same for simplicity.
self.track_width = max(self.horiz_track_width,self.vert_track_width)
2018-12-05 02:08:47 +01:00
debug.info(1,"Track width: {:.3f}".format(self.track_width))
self.track_space = max(self.horiz_layer_spacing,self.vert_layer_spacing)
debug.info(1,"Track space: {:.3f}".format(self.track_space))
self.track_wire = self.track_width - self.track_space
debug.info(1,"Track wire width: {:.3f}".format(self.track_wire))
2018-12-03 20:09:17 +01:00
self.track_widths = vector([self.track_width] * 2)
self.track_factor = vector([1/self.track_width] * 2)
2018-12-05 02:08:47 +01:00
debug.info(2,"Track factor: {}".format(self.track_factor))
2018-12-03 20:09:17 +01:00
# When we actually create the routes, make them the width of the track (minus 1/2 spacing on each side)
self.layer_widths = [self.track_wire, 1, self.track_wire]
def same_lpp(self, lpp1, lpp2):
"""
Check if the layers and purposes are the same.
Ignore if purpose is a None.
"""
if lpp1[1] == None or lpp2[1] == None:
return lpp1[0] == lpp2[0]
return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1]
def get_zindex(self, lpp):
if self.same_lpp(lpp, self.horiz_lpp):
return 0
else:
return 1
def get_layer(self, zindex):
if zindex==1:
return self.vert_layer_name
elif zindex==0:
return self.horiz_layer_name
else:
debug.error("Invalid zindex {}".format(zindex),-1)
def get_supply_layer_width_space(self, zindex):
2018-12-03 20:09:17 +01:00
"""
These are the width and spacing of a supply layer given a supply rail
of the given number of min wire widths.
"""
if zindex==1:
layer_name = self.vert_layer_name
elif zindex==0:
layer_name = self.horiz_layer_name
else:
debug.error("Invalid zindex for track", -1)
min_wire_width = drc("minwidth_{0}".format(layer_name), 0, math.inf)
2018-12-03 20:09:17 +01:00
min_width = drc("minwidth_{0}".format(layer_name), self.rail_track_width*min_wire_width, math.inf)
min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), self.rail_track_width*min_wire_width, math.inf)
2018-12-03 20:09:17 +01:00
return (min_width,min_spacing)