Exemplo n.º 1
0
def pos_mode(args):
    pytrellis.load_database("../../../database")

    cfg = FuzzConfig(job="FINDNETS_R{}C{}".format(args.row, args.col),
                     family="MachXO2",
                     device="LCMXO2-1200HC",
                     ncl="plc2route.ncl",
                     tiles=[])
    cfg.setup()

    netdata = isptcl.get_wires_at_position(cfg.ncd_prf, (args.row, args.col))
    netnames = [x[0] for x in netdata]
    arcs = isptcl.get_arcs_on_wires(cfg.ncd_prf, netnames, False,
                                    defaultdict(lambda: str("mark")))

    with open(
            "r{}c{}_{}out.txt".format(args.row, args.col,
                                      "a_" if args.a else ""), "w") as fp:
        for (k, v) in arcs.items():
            print("{}:".format(k), file=fp)
            for c in v:
                if isinstance(c, isptcl.AmbiguousArc):
                    print(str(c), file=fp)
                else:
                    if not args.a:
                        print("{} --> {}".format(c[0], c[1]), file=fp)

            fp.flush()
            print("", file=fp)
Exemplo n.º 2
0
def net_mode(args):
    pytrellis.load_database("../../../database")

    cfg = FuzzConfig(job="FINDNETS_NETS_{}".format(args.nets[0]),
                     family="MachXO2",
                     device="LCMXO2-1200HC",
                     ncl="plc2route.ncl",
                     tiles=[])
    cfg.setup()

    arcs = isptcl.get_arcs_on_wires(cfg.ncd_prf, args.nets, False,
                                    defaultdict(lambda: str("mark")))

    with open("{}_out.txt".format(args.nets[0]), "w") as fp:
        for (k, v) in arcs.items():
            print("{}:".format(k), file=fp)
            for c in v:
                if isinstance(c, isptcl.AmbiguousArc):
                    print(str(c), file=fp)
                else:
                    print("{} --> {}".format(c[0], c[1]), file=fp)

            fp.flush()
            print("", file=fp)
Exemplo n.º 3
0
def fuzz_interconnect_with_netnames(
        config,
        netnames,
        netname_predicate=lambda x, nets: True,
        arc_predicate=lambda x, nets: True,
        fc_predicate=lambda x, nets: True,
        bidir=False,
        netname_filter_union=False,
        full_mux_style=False,
        fc_prefix="",
        nonlocal_prefix=""):
    """
    Fuzz interconnect given a list of netnames to analyse. Arcs associated these netnames will be found using the Tcl
    API and bits identified as described above.

    :param config: FuzzConfig instance containing target device and tile(s) of interest
    :param netnames: A list of netnames in Lattice (un-normalised) format to analyse
    :param netname_predicate: a predicate function which should return True if a netname is of interest, given
    the netname and the set of all nets
    :param arc_predicate: a predicate function which should return True if an arc, given the arc as a (source, sink)
    tuple and the set of all netnames, is of interest
    :param bidir: if True, arcs driven by as well as driving the given netnames will be considered during analysis
    :param netname_filter_union: if True, arcs will be included if either net passes netname_predicate, if False both
    nets much pass the predicate.
    :param full_mux_style: if True, is a full mux, and all 0s is considered a valid config bit possibility
    :param fc_prefix: add a prefix to non-global fixed connections for device-specific fuzzers
    """
    net_arcs = isptcl.get_arcs_on_wires(config.ncd_prf, netnames, not bidir)
    baseline_bitf = config.build_design(config.ncl, {}, "base_")
    baseline_chip = pytrellis.Bitstream.read_bit(baseline_bitf).deserialise_chip()

    max_row = baseline_chip.get_max_row()
    max_col = baseline_chip.get_max_col()

    def normalise_arc_in_tile(tile, arc):
        return tuple(nets.normalise_name((max_row, max_col), tile, x) for x in arc)

    def add_nonlocal_prefix(wire):
        if wire.startswith("G_"):
            return wire
        m = re.match(r'([NS]\d+)?([EW]\d+)?_.*', wire)
        if m:
            for g in m.groups():
                if g is not None and int(g[1:]) >= 3:
                    return nonlocal_prefix + wire
        return wire

    def per_netname(net):
        # Get a unique prefix from the thread ID
        prefix = "thread{}_".format(threading.get_ident())
        assoc_arcs = net_arcs[net]
        # Obtain the set of databases
        tile_dbs = {tile: pytrellis.get_tile_bitdata(
            pytrellis.TileLocator(config.family, config.device, tiles.type_from_fullname(tile))) for tile in
            config.tiles}
        # First filter using netname predicate
        if netname_filter_union:
            assoc_arcs = filter(lambda x: netname_predicate(x[0], netnames) and netname_predicate(x[1], netnames),
                                assoc_arcs)
        else:
            assoc_arcs = filter(lambda x: netname_predicate(x[0], netnames) or netname_predicate(x[1], netnames),
                                assoc_arcs)
        # Then filter using the arc predicate
        fuzz_arcs = list(filter(lambda x: arc_predicate(x, netnames), assoc_arcs))

        # Ful fullmux mode only
        changed_bits = set()
        arc_tiles = {}
        tiles_changed = set()

        for arc in fuzz_arcs:
            # Route statement containing arc for NCL file
            arc_route = "route\n\t\t\t" + arc[0] + "." + arc[1] + ";"
            # Build a bitstream and load it using libtrellis
            arc_bitf = config.build_design(config.ncl, {"route": arc_route}, prefix)
            arc_chip = pytrellis.Bitstream.read_bit(arc_bitf).deserialise_chip()
            # Compare the bitstream with the arc to the baseline bitstream
            diff = arc_chip - baseline_chip
            if (not full_mux_style) or len(fuzz_arcs) == 1:
                if len(diff) == 0:
                    # No difference means fixed interconnect
                    # We consider this to be in the first tile if multiple tiles are being analysed
                    if fc_predicate(arc, netnames):
                        norm_arc = normalise_arc_in_tile(config.tiles[0], arc)
                        fc = pytrellis.FixedConnection()
                        norm_arc = [fc_prefix + _ if not _.startswith("G_") else _ for _ in norm_arc]
                        norm_arc = [add_nonlocal_prefix(_) for _ in norm_arc]
                        fc.source, fc.sink = norm_arc
                        tile_dbs[config.tiles[0]].add_fixed_conn(fc)
                else:
                    for tile in config.tiles:
                        if tile in diff:
                            # Configurable interconnect in <tile>
                            norm_arc = normalise_arc_in_tile(tile, arc)
                            norm_arc = [add_nonlocal_prefix(_) for _ in norm_arc]
                            ad = pytrellis.ArcData()
                            ad.source, ad.sink = norm_arc
                            ad.bits = pytrellis.BitGroup(diff[tile])
                            tile_dbs[tile].add_mux_arc(ad)
            else:
                arc_tiles[arc] = {}
                for tile in config.tiles:
                    if tile in diff:
                        tiles_changed.add(tile)
                        for bit in diff[tile]:
                            changed_bits.add((tile, bit.frame, bit.bit))
                    arc_tiles[arc][tile] = arc_chip.tiles[tile]

        if full_mux_style and len(fuzz_arcs) > 1:
            for tile in tiles_changed:
                for arc in arc_tiles:
                    bg = pytrellis.BitGroup()
                    for (btile, bframe, bbit) in changed_bits:
                        if btile == tile:
                            state = arc_tiles[arc][tile].cram.bit(bframe, bbit)
                            cb = pytrellis.ConfigBit()
                            cb.frame = bframe
                            cb.bit = bbit
                            cb.inv = (state == 0)
                            bg.bits.add(cb)
                    ad = pytrellis.ArcData()
                    ad.source, ad.sink = normalise_arc_in_tile(tile, arc)
                    ad.bits = bg
                    tile_dbs[tile].add_mux_arc(ad)
        # Flush database to disk
        for tile, db in tile_dbs.items():
            db.save()

    fuzzloops.parallel_foreach(netnames, per_netname)
Exemplo n.º 4
0
def filter_mode(args):
    span1_re = re.compile(r'R\d+C\d+_[VH]01[NESWTLBR]\d{4}')
    location = (args.row, args.col)

    def netname_predicate(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)

    def arc_predicate(arc, netnames):
        return True

    def fc_predicate(arc, netnames):
        return True

    pytrellis.load_database("../../../database")

    cfg = FuzzConfig(job="FINDNETS_FILTER_R{}C{}".format(args.row, args.col),
                     family="MachXO2",
                     device="LCMXO2-1200HC",
                     ncl="plc2route.ncl",
                     tiles=[])
    cfg.setup()

    # fuzz_interconnect
    netdata = isptcl.get_wires_at_position(cfg.ncd_prf, (args.row, args.col))
    netnames = [x[0] for x in netdata]

    extra_netnames = []
    if args.s:
        for net in netnames:
            m = re.match("R(\d+)C(\d+)_V01N(\d{4})", net)
            if m:
                row = int(m.group(1))
                col = int(m.group(2))
                idn = m.group(3)
                if row == location[0] + 1 and col == location[1]:
                    fixednet = "R{}C{}_V01N{}".format(location[0] - 1, col,
                                                      idn)
                    print("added {}".format(fixednet))
                    extra_netnames.append(fixednet)
        netnames = extra_netnames + netnames

    if args.f and not args.n:
        netnames = list(
            filter(lambda x: netname_predicate(x, netnames), netnames))

    # fuzz_interconnect_with_netnames
    arcs = isptcl.get_arcs_on_wires(cfg.ncd_prf, netnames, not args.f,
                                    defaultdict(lambda: str("mark")))

    def per_netname(net):
        assoc_arcs = arcs[net]

        if args.n:
            filt_net_pred = list(
                itertools.filterfalse(
                    lambda x: netname_predicate(x[0], netnames) and
                    netname_predicate(x[1], netnames), assoc_arcs.copy()))
            assoc_arcs = list(
                filter(
                    lambda x: netname_predicate(x[0], netnames) and
                    netname_predicate(x[1], netnames), assoc_arcs))
        else:
            filt_net_pred = list(
                itertools.filterfalse(
                    lambda x: netname_predicate(x[0], netnames) or
                    netname_predicate(x[1], netnames), assoc_arcs.copy()))
            assoc_arcs = list(
                filter(
                    lambda x: netname_predicate(x[0], netnames) or
                    netname_predicate(x[1], netnames), assoc_arcs))

        filt_arcs_pred = list(
            itertools.filterfalse(lambda x: arc_predicate(x, netnames),
                                  assoc_arcs.copy()))
        fuzz_arcs = list(
            filter(lambda x: arc_predicate(x, netnames), assoc_arcs))

        filt_fc_pred = list(
            itertools.filterfalse(lambda x: fc_predicate(x, netnames),
                                  fuzz_arcs.copy()))

        return (fuzz_arcs, filt_net_pred, filt_arcs_pred, filt_fc_pred)

    # Write to file, describing which nets did/didn't make the cut.
    with open("r{}c{}_filter.txt".format(args.row, args.col), "w") as fp:

        def print_arc(arc):
            if isinstance(arc, isptcl.AmbiguousArc):
                print(str(arc), file=fp)
            else:
                print("{} --> {}".format(arc[0], arc[1]), file=fp)

        print("Args: {}".format(vars(args)), file=fp)
        print("", file=fp)

        print("Extra nets (span 1s):", file=fp)
        for net in extra_netnames:
            print("{}:".format(net), file=fp)
        print("", file=fp)

        print("Filters:", file=fp)
        print("Netname:\n{}".format(inspect.getsource(netname_predicate)),
              file=fp)
        print("Arc:\n{}".format(inspect.getsource(arc_predicate)), file=fp)
        print("FC:\n{}".format(inspect.getsource(fc_predicate)), file=fp)
        print("", file=fp)

        for net in netnames:
            print("{}:".format(net), file=fp)

            (fuzz, filt_net, filt_arc, filt_fc) = per_netname(net)
            print("Arcs to fuzz:", file=fp)
            for f in fuzz:
                print_arc(f)
            print("Arcs filtered by netname_predicate:", file=fp)
            for f in filt_net:
                print_arc(f)
            print("Arcs filtered by arc_predicate:", file=fp)
            for f in filt_arc:
                print_arc(f)
            print("Would be filtered by fc_predicate (if fixed connection):",
                  file=fp)
            for f in filt_fc:
                print_arc(f)

            fp.flush()
            print("", file=fp)