1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
"""
Utilities for fuzzing non-routing configuration. This is the counterpart to interconnect.py
"""
import threading
import tiles
import pytrellis
def fuzz_word_setting(config, name, length, get_ncl_substs, empty_bitfile=None):
"""
Fuzz a multi-bit setting, such as LUT initialisation
:param config: FuzzConfig instance containing target device and tile of interest
:param name: name of the setting to store in the database
:param length: number of bits in the setting
:param get_ncl_substs: a callback function, that is first called with an array of bits to create a design with that setting
:param empty_bitfile: a path to a bit file without the parameter included, optional, which is used to determine the
default value
"""
prefix = "thread{}_".format(threading.get_ident())
tile_dbs = {tile: pytrellis.get_tile_bitdata(
pytrellis.TileLocator(config.family, config.device, tiles.type_from_fullname(tile))) for tile in
config.tiles}
if empty_bitfile is not None:
none_chip = pytrellis.Bitstream.read_bit(empty_bitfile).deserialise_chip()
else:
none_chip = None
baseline_bitf = config.build_design(config.ncl, get_ncl_substs([False for _ in range(length)]), prefix)
baseline_chip = pytrellis.Bitstream.read_bit(baseline_bitf).deserialise_chip()
wsb = {tile: pytrellis.WordSettingBits() for tile in
config.tiles}
is_empty = {tile: True for tile in config.tiles}
for t in config.tiles:
wsb[t].name = name
for i in range(length):
bit_bitf = config.build_design(config.ncl, get_ncl_substs([(_ == i) for _ in range(length)]), prefix)
bit_chip = pytrellis.Bitstream.read_bit(bit_bitf).deserialise_chip()
diff = bit_chip - baseline_chip
for tile in config.tiles:
if tile in diff:
wsb[tile].bits.append(pytrellis.BitGroup(diff[tile]))
is_empty[tile] = False
else:
wsb[tile].bits.append(pytrellis.BitGroup())
if none_chip is not None:
if wsb[tile].bits[i].match(none_chip.tiles[tile].cram):
wsb[tile].defval.append(True)
else:
wsb[tile].defval.append(False)
for t in config.tiles:
if not is_empty[t]:
tile_dbs[t].add_setting_word(wsb[t])
tile_dbs[t].save()
def fuzz_enum_setting(config, name, values, get_ncl_substs, empty_bitfile=None, include_zeros=True, ignore_cover=None,
opt_pref=None, ignore_bits=None):
"""
Fuzz a setting with multiple possible values
:param config: FuzzConfig instance containing target device and tile of interest
:param name: name of the setting to store in the database
:param values: list of values taken by the enum
:param get_ncl_substs: a callback function, that is first called with an array of bits to create a design with that setting
:param empty_bitfile: a path to a bit file without the parameter included, optional, which is used to determine the
default value
:param include_zeros: if set, bits set to zero are not included in db. Needed for settings such as CEMUX which share
bits with routing muxes to prevent conflicts.
:param ignore_cover: these values will also be checked, and bits changing between these will be ignored
:param opt_pref: bits exclusively set in these options will be included in all options overriding include_zeros
"""
prefix = "thread{}_".format(threading.get_ident())
tile_dbs = {tile: pytrellis.get_tile_bitdata(
pytrellis.TileLocator(config.family, config.device, tiles.type_from_fullname(tile))) for tile in
config.tiles}
if empty_bitfile is not None:
none_chip = pytrellis.Bitstream.read_bit(empty_bitfile).deserialise_chip()
else:
none_chip = None
changed_bits = set()
prev_tiles = {}
tiles_changed = set()
for val in values:
print("****** Fuzzing {} = {} ******".format(name, val))
bit_bitf = config.build_design(config.ncl, get_ncl_substs(val), prefix)
bit_chip = pytrellis.Bitstream.read_bit(bit_bitf).deserialise_chip()
for prev in prev_tiles.values():
for tile in config.tiles:
diff = bit_chip.tiles[tile].cram - prev[tile]
if len(diff) > 0:
tiles_changed.add(tile)
for bit in diff:
changed_bits.add((tile, bit.frame, bit.bit))
prev_tiles[val] = {}
for tile in config.tiles:
prev_tiles[val][tile] = bit_chip.tiles[tile].cram
if ignore_cover is not None:
ignore_changed_bits = set()
ignore_prev_tiles = {}
for ival in ignore_cover:
print("****** Fuzzing {} = {} [to ignore] ******".format(name, ival))
bit_bitf = config.build_design(config.ncl, get_ncl_substs(ival), prefix)
bit_chip = pytrellis.Bitstream.read_bit(bit_bitf).deserialise_chip()
for prev in ignore_prev_tiles.values():
for tile in config.tiles:
diff = bit_chip.tiles[tile].cram - prev[tile]
if len(diff) > 0:
for bit in diff:
ignore_changed_bits.add((tile, bit.frame, bit.bit))
ignore_prev_tiles[ival] = {}
for tile in config.tiles:
ignore_prev_tiles[ival][tile] = bit_chip.tiles[tile].cram
for ibit in ignore_changed_bits:
if ibit in changed_bits:
changed_bits.remove(ibit)
for tile in tiles_changed:
esb = pytrellis.EnumSettingBits()
esb.name = name
pref_exclusive = {}
if opt_pref is not None:
for val in values:
for (btile, bframe, bbit) in changed_bits:
if btile == tile:
state = prev_tiles[val][tile].bit(bframe, bbit)
if state:
if val in opt_pref:
if (btile, bframe, bbit) not in pref_exclusive:
pref_exclusive[(btile, bframe, bbit)] = True
else:
pref_exclusive[(btile, bframe, bbit)] = False
for val in values:
bg = pytrellis.BitGroup()
for (btile, bframe, bbit) in changed_bits:
if btile == tile:
state = prev_tiles[val][tile].bit(bframe, bbit)
if state == 0 and not include_zeros and (
none_chip is not None and not none_chip.tiles[tile].cram.bit(bframe, bbit)) \
and (
(btile, bframe, bbit) not in pref_exclusive or not pref_exclusive[(btile, bframe, bbit)]):
continue
if ignore_bits is not None and ignore_bits.count((btile, bframe, bbit)):
continue
cb = pytrellis.ConfigBit()
cb.frame = bframe
cb.bit = bbit
cb.inv = (state == 0)
bg.bits.add(cb)
esb.options[val] = bg
if none_chip is not None and bg.match(none_chip.tiles[tile].cram):
esb.defval = val
tile_dbs[tile].add_setting_enum(esb)
tile_dbs[tile].save()
|