From 86fce0fee3b47215e87feec60ccc126fe00e9931 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 16 Oct 2018 14:36:59 -0700 Subject: [PATCH] segprint: cleanup, fix Signed-off-by: John McMaster --- utils/segprint.py | 357 +++++++++++++++++++++++++++------------------- 1 file changed, 208 insertions(+), 149 deletions(-) diff --git a/utils/segprint.py b/utils/segprint.py index cbc73403..ef0f9d49 100755 --- a/utils/segprint.py +++ b/utils/segprint.py @@ -1,89 +1,13 @@ #!/usr/bin/env python3 -import getopt, sys, os, json, re - -flag_z = False -flag_b = False -flag_d = False -flag_D = False +import sys, os, json, re -def usage(): - print("Usage: %s [options] [segments/tiles]" % sys.argv[0]) - print("") - print(" -z") - print(" do not print a 'seg' header for empty segments") - print("") - print(" -b") - print(" print bits outside of known segments") - print("") - print(" -d") - print(" decode known segment bits and write them as tags") - print("") - print(" -D") - print(" decode known segment bits and omit them in the output") - print("") - sys.exit(0) +class NoDB(Exception): + pass -try: - opts, args = getopt.getopt(sys.argv[1:], "zbdD") -except: - usage() - -if len(args) == 0: - usage() - -for o, a in opts: - if o == "-z": - flag_z = True - elif o == "-b": - flag_b = True - elif o == "-d": - flag_d = True - elif o == "-D": - flag_D = True - else: - usage() - -with open("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"), - os.getenv("XRAY_DATABASE")), "r") as f: - new_grid = json.load(f) - -# TODO: Migrate to new tilegrid format via library. -grid = {'tiles': new_grid, 'segments': {}} - -for tile in grid['tiles'].values(): - if 'segment' in tile: - segment = tile['segment'] - grid['segments'][segment] = { - 'baseaddr': [ - tile['baseaddr'], - tile['offset'], - ], - 'type': tile['segment_type'], - 'frames': tile['frames'], - 'words': tile['words'], - } - -bitdata = dict() - -# print("Loading %s." % sys.argv[1]) -with open(args[0], "r") as f: - for line in f: - line = line.split("_") - frame = int(line[1], 16) - wordidx = int(line[2], 10) - bitidx = int(line[3], 10) - - if frame not in bitdata: - bitdata[frame] = dict() - - if wordidx not in bitdata[frame]: - bitdata[frame][wordidx] = set() - - bitdata[frame][wordidx].add(bitidx) - +# cache segbitsdb = dict() @@ -91,18 +15,24 @@ def get_database(segtype): if segtype in segbitsdb: return segbitsdb[segtype] + main_fn = "%s/%s/segbits_%s.db" % ( + os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), + segtype.lower()) + int_fn = "%s/%s/segbits_int_%s.db" % ( + os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), + segtype[-1].lower()) + + if not os.path.exists(main_fn) or not os.path.exists(int_fn): + raise NoDB(segtype) + segbitsdb[segtype] = list() - with open("%s/%s/segbits_%s.db" % (os.getenv("XRAY_DATABASE_DIR"), - os.getenv("XRAY_DATABASE"), segtype), - "r") as f: + with open(main_fn, "r") as f: for line in f: line = line.split() segbitsdb[segtype].append(line) - with open("%s/%s/segbits_int_%s.db" % - (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), - segtype[-1]), "r") as f: + with open(int_fn, "r") as f: for line in f: line = line.split() segbitsdb[segtype].append(line) @@ -110,73 +40,50 @@ def get_database(segtype): return segbitsdb[segtype] -def handle_segment(segname): - if segname is None: - segframes = dict() - for segname, segdata in grid["segments"].items(): - framebase = int(segdata["baseaddr"][0], 16) - for i in range(segdata["frames"]): - if (framebase + i) not in segframes: - segframes[framebase + i] = set() - for j in range(segdata["baseaddr"][1], - segdata["baseaddr"][1] + segdata["words"]): - segframes[framebase + i].add(j) - for frame in sorted(bitdata.keys()): - for wordidx in sorted(bitdata[frame].keys()): - if frame in segframes and wordidx in segframes[frame]: - continue - for bitidx in sorted(bitdata[frame][wordidx]): - print("bit_%08x_%03d_%02d" % (frame, wordidx, bitidx)) - return - if ":" in segname: - seg1, seg2 = segname.split(":") +def handle_split_segment( + segname, grid, bitdata, flag_d, flag_D, omit_empty_segs): + seg1, seg2 = segname.split(":") - if seg1 in grid["tiles"]: - seg1 = grid["tiles"][seg1]["segment"] + if seg1 in grid["tiles"]: + seg1 = grid["tiles"][seg1]["segment"] - if seg2 in grid["tiles"]: - seg2 = grid["tiles"][seg2]["segment"] + if seg2 in grid["tiles"]: + seg2 = grid["tiles"][seg2]["segment"] - seginfo1 = grid["segments"][seg1] - seginfo2 = grid["segments"][seg2] + seginfo1 = grid["segments"][seg1] + seginfo2 = grid["segments"][seg2] - frame1 = int(seginfo1["baseaddr"][0], 16) - word1 = int(seginfo1["baseaddr"][1]) + frame1 = int(seginfo1["baseaddr"][0], 16) + word1 = int(seginfo1["baseaddr"][1]) - frame2 = int(seginfo2["baseaddr"][0], 16) - word2 = int(seginfo2["baseaddr"][1]) + frame2 = int(seginfo2["baseaddr"][0], 16) + word2 = int(seginfo2["baseaddr"][1]) - if frame1 > frame2: - frame1, frame2 = frame2, frame1 + if frame1 > frame2: + frame1, frame2 = frame2, frame1 - if word1 > word2: - word1, word2 = word2, word1 + if word1 > word2: + word1, word2 = word2, word1 - segs = list() + segs = list() - for seg, seginfo in sorted(grid["segments"].items()): - frame = int(seginfo["baseaddr"][0], 16) - word = int(seginfo["baseaddr"][1]) - if frame1 <= frame <= frame2 and word1 <= word <= word2: - segs.append((frame, word, seg)) + for seg, seginfo in sorted(grid["segments"].items()): + frame = int(seginfo["baseaddr"][0], 16) + word = int(seginfo["baseaddr"][1]) + if frame1 <= frame <= frame2 and word1 <= word <= word2: + segs.append((frame, word, seg)) - for _, _, seg in sorted(segs): - handle_segment(seg) - return + for _, _, seg in sorted(segs): + handle_segment(segname, grid, bitdata, flag_d, flag_D, omit_empty_segs) - if segname in grid["tiles"]: - segname = grid["tiles"][segname]["segment"] - - seginfo = grid["segments"][segname] +def mk_segbits(seginfo, bitdata): baseframe = int(seginfo["baseaddr"][0], 16) basewordidx = int(seginfo["baseaddr"][1]) numframes = int(seginfo["frames"]) numwords = int(seginfo["words"]) segbits = set() - segtags = set() - for frame in range(baseframe, baseframe + numframes): if frame not in bitdata: continue @@ -187,8 +94,38 @@ def handle_segment(segname): segbits.add( "%02d_%02d" % (frame - baseframe, 32 * (wordidx - basewordidx) + bitidx)) + return segbits - if flag_d or flag_D: + +def print_unknown_bits(grid, bitdata): + ''' + Print bits not covered by known tiles + ''' + + # Index all known locations + # seggrames[address] = set() + # where set contains word numbers + segframes = dict() + for segname, segdata in grid["segments"].items(): + framebase = int(segdata["baseaddr"][0], 16) + for i in range(segdata["frames"]): + words = segframes.setdefault(framebase + i, set()) + for j in range(segdata["baseaddr"][1], + segdata["baseaddr"][1] + segdata["words"]): + words.add(j) + + # print uncovered locations + print('Non-database bits:') + for frame in sorted(bitdata.keys()): + for wordidx in sorted(bitdata[frame].keys()): + if frame in segframes and wordidx in segframes[frame]: + continue + for bitidx in sorted(bitdata[frame][wordidx]): + print("bit_%08x_%03d_%02d" % (frame, wordidx, bitidx)) + + +def seg_decode(flag_d, seginfo, segbits, segtags): + try: for entry in get_database(seginfo["type"]): match_entry = True for bit in entry[1:]: @@ -202,10 +139,42 @@ def handle_segment(segname): segbits.remove(bit) if flag_d: segtags.add(entry[0]) + except NoDB: + print("WARNING: failed to load DB for %s" % seginfo["type"]) - if not flag_z or len(segbits) > 0 or len(segtags) > 0: + +def handle_segment(segname, grid, bitdata, flag_d, flag_D, omit_empty_segs): + ''' + segname: tile name + ''' + + assert segname + + # ? probably legacy + #if ":" in segname: + # handle_split_segment(segname, grid, bitdata, flag_d, flag_D, omit_empty_segs) + # return + + # compatibility? + # now dealing only with tile names...? + #if segname in grid["tiles"]: + # segname = grid["tiles"][segname]["segment"] + + # only print bitstream tiles + if segname not in grid["segments"]: + return + seginfo = grid["segments"][segname] + + segtags = set() + segbits = mk_segbits(seginfo, bitdata) + + if flag_d or flag_D: + seg_decode(flag_d, seginfo, segbits, segtags) + + # Found something to print? + if not omit_empty_segs or len(segbits) > 0 or len(segtags) > 0: print() - print("seg %s" % segname) + print("tile %s" % segname) for bit in sorted(segbits): print("bit %s" % bit) @@ -214,15 +183,105 @@ def handle_segment(segname): print("tag %s" % tag) -if flag_b: - handle_segment(None) +def load_bitdata(bits_file): + bitdata = dict() -if len(args) == 1: - seglist = list() - for seg, seginfo in grid["segments"].items(): - seglist.append((seginfo["baseaddr"][0], -seginfo["baseaddr"][1], seg)) - for _, _, seg in sorted(seglist): - handle_segment(seg) -else: - for arg in args[1:]: - handle_segment(arg) + with open(bits_file, "r") as f: + for line in f: + line = line.split("_") + frame = int(line[1], 16) + wordidx = int(line[2], 10) + bitidx = int(line[3], 10) + + if frame not in bitdata: + bitdata[frame] = dict() + + if wordidx not in bitdata[frame]: + bitdata[frame][wordidx] = set() + + bitdata[frame][wordidx].add(bitidx) + return bitdata + + +def mk_grid(): + with open("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"), + os.getenv("XRAY_DATABASE")), "r") as f: + new_grid = json.load(f) + + # TODO: Migrate to new tilegrid format via library. + grid = {'tiles': new_grid, 'segments': {}} + + for tile_name, tile in grid['tiles'].items(): + bits = tile.get('bits', None) + if not bits: + continue + block = bits.get('CLB_IO_CLK', None) + if not block: + continue + + grid['segments'][tile_name] = { + 'baseaddr': [ + block['baseaddr'], + block['offset'], + ], + 'type': tile['type'], + 'frames': block['frames'], + 'words': block['words'], + } + return grid + + +def run( + bits_file, + segments, + omit_empty_segs=False, + flag_b=False, + flag_d=False, + flag_D=False): + grid = mk_grid() + + bitdata = load_bitdata(bits_file) + + if flag_b: + print_unknown_bits(grid, bitdata) + + if segments: + for segment in segments: + handle_segment( + segment, grid, bitdata, flag_d, flag_D, omit_empty_segs) + else: + for segname in sorted(grid['tiles'].keys()): + handle_segment( + segname, grid, bitdata, flag_d, flag_D, omit_empty_segs) + + +def main(): + import argparse + + parser = argparse.ArgumentParser(description='') + + parser.add_argument('--verbose', action='store_true', help='') + parser.add_argument( + '-z', + action='store_true', + help="do not print a 'seg' header for empty segments") + parser.add_argument( + '-b', action='store_true', help='print bits outside of known segments') + parser.add_argument( + '-d', + action='store_true', + help='decode known segment bits and write them as tags') + # XXX: possibly broken, or we have missing DB data + parser.add_argument( + '-D', + action='store_true', + help='decode known segment bits and omit them in the output') + parser.add_argument('bits_file', help='') + parser.add_argument('segments', nargs='*', help='') + args = parser.parse_args() + + run(args.bits_file, args.segments, args.z, args.b, args.d, args.D) + + +if __name__ == '__main__': + main()