blob: 42d8c328ac2f8709c968b422831c77a1a56d3c19 [file] [log] [blame]
from collections import defaultdict
from itertools import product
from fuzzconfig import FuzzConfig
import interconnect
import nets
import pytrellis
import re
import argparse
import isptcl
import mk_nets
span1_re = re.compile(r'R\d+C\d+_[VH]01[NESWTLBR]\d{4}')
jofx_re = re.compile(r'R\d+C\d+_JOFX\d')
def nn_filter(net, netnames):
""" Match nets that are: in the tile according to Tcl, global nets, or span-1 nets that are accidentally
left out by Tcl"""
return net in netnames or nets.machxo2.is_global(net) or span1_re.match(net)
# JOFX source connections are conjectured to not go to anything.
# Also ignore edge connections.
# TODO: We should probably ignore KEEP connections too, but right now am unsure.
def fc_filter(arc, netnames):
return not jofx_re.match(arc[0]) and not (nets.general_routing_re.match(arc[0]) and nets.general_routing_re.match(arc[1]))
# Bank of None means that the I/O connections are in another tile.
jobs = [
{
"pos" : (12, 11),
"cfg" : FuzzConfig(job="PIOROUTEB", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["PB11:PIC_B0"]),
"missing_nets" : None,
"nn_filter": nn_filter,
"bank" : "B",
},
{
"pos" : (11, 11),
"cfg" : FuzzConfig(job="PIOROUTEB_CIB", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["CIB_R11C11:CIB_PIC_B0"]),
# A bug in the span1 fix prevents span1 nets from being included.
# Just fuzz manually for now.
"missing_nets" : ["R10C11_V01N0001", "R10C11_V01N0101"],
"nn_filter": nn_filter,
"bank" : None,
},
{
"pos" : (10, 1),
"cfg" : FuzzConfig(job="PIOROUTEL", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["PL10:PIC_L0"]),
"missing_nets" : None,
"nn_filter": nn_filter,
"bank" : "L"
},
# Probably the same thing as PIC_L0 plus some additional fixed connections?
{
"pos" : (11, 1),
"cfg" : FuzzConfig(job="PIOROUTELLC0", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["PL11:LLC0"]),
"missing_nets" : None,
"nn_filter": nn_filter,
"bank" : "L"
},
# 4
{
"pos" : (10, 22),
"cfg" : FuzzConfig(job="PIOROUTER", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["PR10:PIC_R0"]),
"missing_nets" : None,
"nn_filter": nn_filter,
"bank" : "R"
},
{
"pos" : (0, 12),
"cfg" : FuzzConfig(job="PIOROUTET", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["PT12:PIC_T0"]),
"missing_nets" : None,
"nn_filter" : lambda x, nets: x.startswith("R0C12"),
"bank" : "T",
},
{
"pos" : (1, 12),
"cfg" : FuzzConfig(job="PIOROUTET_CIB", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["CIB_R1C12:CIB_PIC_T0"]),
"missing_nets" : None,
"nn_filter": nn_filter,
"bank" : None,
},
{
"pos" : (9, 1),
"cfg" : FuzzConfig(job="PIOROUTELS0", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["PL9:PIC_LS0"]),
"missing_nets" : None,
"nn_filter": nn_filter,
"bank" : "LS",
},
# 8
{
"pos" : (3, 22),
"cfg" : FuzzConfig(job="PIOROUTERS0", family="MachXO2", device="LCMXO2-1200HC", ncl="pioroute.ncl",
tiles=["PR3:PIC_RS0"]),
"missing_nets" : None,
"nn_filter": nn_filter,
"bank" : "RS",
},
]
def main(args):
pytrellis.load_database("../../../database")
for job in [jobs[i] for i in args.ids]:
cfg = job["cfg"]
cfg.setup()
if args.i:
# Fuzz basic routing, ignore fixed connections to/from I/O pads.
interconnect.fuzz_interconnect(config=cfg, location=job["pos"],
netname_predicate=job["nn_filter"],
netdir_override=defaultdict(lambda : str("ignore")),
fc_predicate=fc_filter,
netname_filter_union=False,
enable_span1_fix=True)
if args.m and job["missing_nets"]:
interconnect.fuzz_interconnect_with_netnames(config=cfg,
netnames=job["missing_nets"],
fc_predicate=fc_filter,
netname_filter_union=False,
bidir=True,
netdir_override=defaultdict(lambda : str("ignore")))
if args.p and job["bank"]:
# I/O connections in the left/right tiles exist as-if a column "0"
# or one past maximum is physically present.
if job["bank"].startswith("R"):
ab_only = job["bank"].endswith("S")
io_nets = mk_nets.io_conns((job["pos"][0], job["pos"][1] + 1), job["bank"], ab_only)
elif job["bank"].startswith("L"):
ab_only = job["bank"].endswith("S")
io_nets = mk_nets.io_conns((job["pos"][0], job["pos"][1] - 1), job["bank"], ab_only)
else:
io_nets = mk_nets.io_conns((job["pos"][0], job["pos"][1]), job["bank"])
io_list = [io[0] for io in io_nets]
override_dict = {io[0]: io[1] for io in io_nets}
print(override_dict)
interconnect.fuzz_interconnect_with_netnames(config=cfg,
netnames=io_list,
fc_predicate=fc_filter,
netname_filter_union=False,
bidir=True,
netdir_override=override_dict)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PIO Routing Fuzzer.")
parser.add_argument("-i", action="store_true", help="Fuzz interconnect.")
parser.add_argument("-m", action="store_true", help="Fuzz missing nets.")
parser.add_argument("-p", action="store_true", help="Fuzz I/O pad connections.")
parser.add_argument(dest="ids", metavar="N", type=int, nargs="*",
default=range(0, len(jobs)), help="Job (indices) to run.")
args = parser.parse_args()
main(args)