Create VCG using nets as nodes rather than pins.

This commit is contained in:
Matt Guthaus 2018-09-11 13:28:28 -07:00
parent add0e3ad68
commit fcc4a75295
2 changed files with 72 additions and 30 deletions

View File

@ -602,6 +602,7 @@ class layout(lef.lef):
""" """
Connect a mapping of pin -> name for a bus. This could be Connect a mapping of pin -> name for a bus. This could be
replaced with a channel router in the future. replaced with a channel router in the future.
NOTE: This has only really been tested with point-to-point connections (not multiple pins on a net).
""" """
(horizontal_layer, via_layer, vertical_layer)=layer_stack (horizontal_layer, via_layer, vertical_layer)=layer_stack
if horizontal: if horizontal:
@ -720,6 +721,7 @@ class layout(lef.lef):
try to minimize the number of tracks -- instead, it picks an order to avoid the vertical try to minimize the number of tracks -- instead, it picks an order to avoid the vertical
conflicts between pins. conflicts between pins.
""" """
local_debug = True
def remove_net_from_graph(pin, g): def remove_net_from_graph(pin, g):
# Remove the pin from the keys # Remove the pin from the keys
@ -732,6 +734,29 @@ class layout(lef.lef):
g[other_pin]=conflicts g[other_pin]=conflicts
return g return g
def vcg_pins_overlap(pins1, pins2, vertical):
# Check all the pin pairs on two nets and return a pin
# overlap if any pin overlaps vertically
for pin1 in pins1:
for pin2 in pins2:
if vcg_pin_overlap(pin1, pin2, vertical):
return True
return False
def vcg_pin_overlap(pin1, pin2, vertical):
# Check for vertical overlap of the two pins
# Pin 1 must be in the "LEFT" set and overlap the right
x_overlap = pin1.lx() < pin2.lx() and abs(pin1.center().x-pin2.center().x)<pitch
# Pin 1 must be in the "TOP" set and overlap the bottom
y_overlap = pin1.by() > pin2.by() and abs(pin1.center().y-pin2.center().y)<pitch
return (not vertical and x_overlap) or (vertical and y_overlap)
if not pitch: if not pitch:
pitch = self.m2_pitch pitch = self.m2_pitch
@ -745,21 +770,37 @@ class layout(lef.lef):
# Initialize the vertical conflict graph (vcg) and make a list of all pins # Initialize the vertical conflict graph (vcg) and make a list of all pins
vcg = {} vcg = {}
# Create names for the nets for the graphs
nets = {}
index = 0
print(route_map)
for pin_connections in route_map:
net_name = "n{}".format(index)
print("N",net_name)
index += 1
nets[net_name] = []
for pin_name in pin_connections:
pin = all_pins[pin_name]
nets[net_name].append(pin)
if local_debug:
import pprint
pprint.pprint(nets)
# Find the vertical pin conflicts # Find the vertical pin conflicts
# FIXME: O(n^2) but who cares for now # FIXME: O(n^2) but who cares for now
for top_name,top_pin in top_pins.items(): for net_name1 in nets:
vcg[top_name]=[] print("NET1:",net_name1)
for bot_name,bot_pin in bottom_pins.items(): vcg[net_name1]=[]
# Remember, vertical is the boolean of the routes in the channel for net_name2 in nets:
# so check the intervals of the pins in the other dimension print("NET2:",net_name2)
x_overlap = abs(top_pin.center().x-bot_pin.center().x)<pitch # Skip yourself
y_overlap = abs(top_pin.center().y-bot_pin.center().y)<pitch if net_name1 == net_name2:
continue
if (vertical and y_overlap) or (not vertical and x_overlap): if vcg_pins_overlap(nets[net_name1], nets[net_name2], vertical):
try: try:
vcg[bot_name].append(top_name) vcg[net_name1].append(net_name2)
except: except:
vcg[bot_name] = [top_name] vcg[net_name1] = [net_name2]
#FIXME: What if we have a cycle? #FIXME: What if we have a cycle?
@ -773,26 +814,27 @@ class layout(lef.lef):
# list of routes to do # list of routes to do
while vcg: while vcg:
#print(vcg) if local_debug:
from pprint import pformat
print("VCG:\n",pformat(vcg))
# get a route from conflict graph with empty fanout set # get a route from conflict graph with empty fanout set
route_pin=None net_name=None
for route_pin,conflicts in vcg.items(): for net_name,conflicts in vcg.items():
if len(conflicts)==0: if len(conflicts)==0:
vcg=remove_net_from_graph(route_pin,vcg) vcg=remove_net_from_graph(net_name,vcg)
break break
else:
# FIXME: We don't support cyclic VCGs right now.
debug.error("Cyclic VCG in channel router.",-1)
# Get the connected pins from the routing map if local_debug:
for pin_connections in route_map: print("Routing:",net_name,pin_connections)
if route_pin in pin_connections:
break
#print("Routing:",route_pin,pin_connections)
# Remove the other pins from the conflict graph too # These are the pins we'll have to connect
for other_pin in pin_connections: pin_list = nets[net_name]
vcg=remove_net_from_graph(other_pin, vcg)
# Create a list of the pins rather than a list of the names # Remove the net from other constriants in the VCG
pin_list = [all_pins[pin_name] for pin_name in pin_connections] vcg=remove_net_from_graph(net_name, vcg)
# Add the trunk route and move up to next track # Add the trunk route and move up to next track
if vertical: if vertical:

View File

@ -23,8 +23,8 @@ class sram_1bank_test(openram_test):
c.words_per_row=1 c.words_per_row=1
debug.info(1, "Single bank, no column mux with control logic") debug.info(1, "Single bank, no column mux with control logic")
a = sram(c, "sram1") #a = sram(c, "sram1")
self.local_check(a, final_verification=True) #self.local_check(a, final_verification=True)
c.num_words=32 c.num_words=32
c.words_per_row=2 c.words_per_row=2