mirror of https://github.com/openXC7/prjxray.git
segprint: cleanup, fix
Signed-off-by: John McMaster <johndmcmaster@gmail.com>
This commit is contained in:
parent
a5c281a4db
commit
86fce0fee3
|
|
@ -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] <bits_file> [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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue