blob: df2d0d4b0e5c70b9ff77a6854c500e75e83fff02 [file] [log] [blame]
"""
Function to get the routed path of a net out of the ncl file
"""
import re
import sys
def slice_pin_to_net(site, pin):
if is_slice(site):
rc = site[:-1]
slice = site[-1]
assert slice in "ABCD"
slicen = "ABCD".index(slice)
if pin in ("A0", "A1", "B0", "B1", "C0", "C1", "D0", "D1", "DI0", "DI1", "M0", "M1", "F0", "F1", "Q0", "Q1"):
pin_idx = int(pin[-1])
pin_name = pin[:-1]
return "{}_{}{}_SLICE".format(rc, pin_name, 2 * slicen + pin_idx)
elif pin in ("CLK", "CE", "LSR", "WCK", "WRE"):
return "{}_{}{}_SLICE".format(rc, pin, slicen)
elif pin == "FCI":
if slice == "A":
return "{}_FCI_SLICE".format(rc)
else:
return "{}_FCI{}_SLICE".format(rc, slice)
elif pin == "FCO":
if slice == "D":
return "{}_FCO_SLICE".format(rc)
else:
return "{}_FCO{}_SLICE".format(rc, slice)
elif pin in ("FXA", "FXB") or pin.startswith("WAD") or pin.startswith("WD"):
return "{}_{}{}_SLICE".format(rc, pin, slice)
elif pin == "OFX0":
return "{}_F5{}_SLICE".format(rc, pin, slice)
elif pin == "OFX1":
return "{}_FX{}_SLICE".format(rc, pin, slice)
else:
assert False, "unhandled pin {} on slice {}".format(pin, slice)
elif is_ebr(site):
rc = site.split("_")[1]
return "{}_J{}_EBR".format(rc, pin)
# TODO: Add other bel types?
def is_slice(site):
return re.match(r'R\d+C\d+[ABCD]', site)
def is_ebr(site):
return re.match(r'EBR_R\d+C\d+', site)
# Convert a parsed net to dict form (sink -> source)
def net_to_dict(signal, bels):
drivers, loads, route = signal
has_slice_driver = False
has_slice_load = False
route_map = {}
for driver in drivers:
if is_slice(bels[driver[0]]) or is_ebr(bels[driver[0]]):
has_slice_driver = True
route_map[slice_pin_to_net(bels[driver[0]], driver[1])] = driver
if not has_slice_driver:
return None
for load in loads:
if is_slice(bels[load[0]]) or is_ebr(bels[load[0]]):
has_slice_load = True
route_map[load] = slice_pin_to_net(bels[load[0]], load[1])
if not has_slice_load:
return None
for arc in route:
route_map[arc[1]] = arc[0]
return route_map
# Print the route for a given net for a given source/sink pair
def print_route(net_dict, driver, load):
route = []
cursor = load
route.append(cursor)
while cursor in net_dict:
cursor = net_dict[cursor]
route.append(cursor)
if cursor != driver:
return
route[0] = ".".join(route[0])
route[-1] = ".".join(route[-1])
print("\t" + " -> ".join(reversed(route)))
# Not a full parser, just for standard Diamond NCLs
def parse_ncl(filename):
signals = {} # name -> (drivers, loads, route)
bels = {}
with open(filename, 'r') as f:
def discard_block():
while True:
line = f.readline().strip()
if "{" in line:
discard_block()
elif "}" in line:
return
def process_comp(name):
while True:
line = f.readline().strip()
if "{" in line:
discard_block()
elif "}" in line:
return
if line.startswith("site"):
bels[name] = line.split(' ', 1)[1].replace(";", "").strip()
def process_signal(name):
drivers = []
loads = []
route = []
def process_pins():
is_drv = True
while True:
line = f.readline().strip()
if line.endswith("\","):
line += f.readline().strip()
if "// loads" in line:
is_drv = False
elif "// drivers" in line:
continue
else:
m = re.match(r'\("?(?P<bel>[^,"]+)"?,\s*"?(?P<pin>[^,"]+)"?\)', line)
assert m, line
pin = (m.group("bel"), m.group("pin"))
if is_drv:
drivers.append(pin)
else:
loads.append(pin)
if ";" in line:
return
def process_route():
while True:
line = f.readline().strip()
m = re.match(r'(?P<a>[A-Za-z0-9_]+)\.(?P<b>[A-Za-z0-9_]+)', line)
assert m
route.append((m.group("a"), m.group("b")))
if ";" in line:
return
while True:
line = f.readline().strip()
if "{" in line:
discard_block()
elif "}" in line:
signals[name] = (drivers, loads, route)
return
elif "signal-pins" in line:
process_pins()
elif "route" in line:
process_route()
while True:
line = f.readline()
if line == "":
break
line = line.strip()
if line.startswith("comp"):
while "{" not in f.readline().strip():
continue
process_comp(line.split(' ', 1)[1].strip().replace('"', ''))
elif line.startswith("signal"):
assert "{" in f.readline().strip()
process_signal(line.split(' ', 1)[1].strip().replace('"', ''))
elif line.startswith("device") or line.startswith("property"):
assert "{" in f.readline().strip()
discard_block()
else:
continue
return signals, bels
def main():
signals, bels = parse_ncl(sys.argv[1])
for name, sig in sorted(signals.items()):
nd = net_to_dict(sig, bels)
drivers, loads, route = sig
if nd is not None:
print("Signal {}:".format(name))
for load in loads:
print_route(nd, drivers[0], load)
print()
if __name__ == "__main__":
main()