blob: 66fe964e544e416f2aa0d6a1438a98b8aaa7433a [file] [log] [blame]
#!/usr/bin/env python3
import pytrellis
import nets
import tiles
import database
import readline
import re
# Interactive connectivity explorer
# All netnames here are canonical
# Key
# <-- net driven by mux
# <== net driven by fixed conn
# --> net drives mux input
# ==> net drives net by fixed conn
def main():
pytrellis.load_database(database.get_db_root())
c = pytrellis.Chip("LFE5U-45F")
chip_size = (c.get_max_row(), c.get_max_col())
# Get fan-in to a net
# Returns (source, configurable, loc)
def get_fanin(net):
drivers = []
npos = tiles.pos_from_name(net, chip_size, 0)
for tile in c.get_all_tiles():
tinf = tile.info
tname = tinf.name
pos = tiles.pos_from_name(tname, chip_size, 0)
if abs(pos[0] - npos[0]) >= 10 or abs(pos[1] - npos[1]) >= 10:
continue
if net.startswith("G_"):
tnet = net
else:
tnet = nets.normalise_name(chip_size, tname, net, 0)
tdb = pytrellis.get_tile_bitdata(pytrellis.TileLocator(c.info.family, c.info.name, tinf.type))
try:
mux = tdb.get_mux_data_for_sink(tnet)
for src in mux.get_sources():
drivers.append((nets.canonicalise_name(chip_size, tname, src, 0), True, tname))
except IndexError:
pass
for fc in tdb.get_fixed_conns():
if fc.sink == tnet:
drivers.append((nets.canonicalise_name(chip_size, tname, fc.source, 0), False, tname))
return drivers
# Get fan-out of a net
# Returns (dest, configurable, loc)
def get_fanout(net):
drivers = []
npos = tiles.pos_from_name(net, chip_size, 0)
for tile in c.get_all_tiles():
tinf = tile.info
tname = tinf.name
pos = tiles.pos_from_name(tname, chip_size, 0)
if abs(pos[0] - npos[0]) >= 12 or abs(pos[1] - npos[1]) >= 12:
continue
if net.startswith("G_"):
tnet = net
else:
tnet = nets.normalise_name(chip_size, tname, net, 0)
tdb = pytrellis.get_tile_bitdata(pytrellis.TileLocator(c.info.family, c.info.name, tinf.type))
for sink in tdb.get_sinks():
mux = tdb.get_mux_data_for_sink(sink)
if tnet in mux.arcs:
drivers.append((nets.canonicalise_name(chip_size, tname, sink, 0), True, tname))
for fc in tdb.get_fixed_conns():
if fc.source == tnet:
drivers.append((nets.canonicalise_name(chip_size, tname, fc.sink, 0), False, tname))
return drivers
# Get all nets at a location
net_tile_cache = {}
non_tile_re = re.compile(r"^([NS]\d+)?([EW]\d+)?[GLR]?_.*")
def get_nets_at(loc):
if loc in net_tile_cache:
return net_tile_cache[loc]
row, col = loc
nets = set()
for tile in c.get_tiles_by_position(row, col):
tinf = tile.info
tdb = pytrellis.get_tile_bitdata(pytrellis.TileLocator(c.info.family, c.info.name, tinf.type))
for sink in tdb.get_sinks():
if not non_tile_re.match(sink):
nets.add(sink)
mux = tdb.get_mux_data_for_sink(sink)
for src in mux.get_sources():
if not non_tile_re.match(src):
nets.add(src)
for fc in tdb.get_fixed_conns():
if not non_tile_re.match(fc.sink):
nets.add(fc.sink)
if not non_tile_re.match(fc.source):
nets.add(fc.source)
nets = list(sorted((["R{}C{}_{}".format(row, col, _) for _ in nets])))
net_tile_cache[loc] = nets
return nets
tile_net_re = re.compile(r"^R\d+C\d+_.*")
def completer(str, idx):
if not tile_net_re.match(str):
return None
loc = tiles.pos_from_name(str, chip_size, 0)
nets = get_nets_at(loc)
for n in nets:
if n.startswith(str):
if idx > 0:
idx -= 1
else:
return n
return None
readline.parse_and_bind("tab: complete")
readline.set_completer(completer)
hist_buf = []
while True:
net = input("> ")
if net.strip() == "":
continue
if net == "quit":
return
if net.isdigit():
idx = int(net)
if idx >= len(hist_buf):
print("Invalid index into last result")
continue
else:
net = hist_buf[idx]
if not tile_net_re.match(net):
print("Bad netname, expected RyCx_...")
continue
hist_buf = []
fi = get_fanin(net)
for drv in fi:
finet, conf, tile = drv
if finet is None: continue
arrow = "<--" if conf else "<=="
print("[{:3d}] {} {} {:25s} [in {}]".format(len(hist_buf), net, arrow, finet, tile))
hist_buf.append(finet)
print()
fo = get_fanout(net)
for src in fo:
fonet, conf, tile = src
if fonet is None: continue
arrow = "-->" if conf else "==>"
print("[{:3d}] {} {} {:25s} [in {}]".format(len(hist_buf), net, arrow, fonet, tile))
hist_buf.append(fonet)
if __name__ == "__main__":
main()