diff --git a/bitMapping2.py b/bitMapping2.py index 08b6f39..14b5265 100644 --- a/bitMapping2.py +++ b/bitMapping2.py @@ -50,12 +50,10 @@ def toStringShort(self): # Add mappings for a particular BRAM primitive into the mappingsn array and return it -def createBitMapping( - words, bits, cell, mappings, verbose, printMappings -): +def createBitMapping(words, bits, cell, mappings, verbose, printMappings): # 1. Flag of whether this is RAMB36E cell or not - ramb36 = (cell.type == "RAMB36E1") or (cell.type == "RAMB36E2") + ramb36 = (cell.type == "RAMB36E1") or (cell.type == "RAMB36E2") # 2. Get the info on this BRAM tile from tilegrid.json #tilegridname = os.environ["XRAY_DIR"] + "/database/" + os.environ[ @@ -196,10 +194,9 @@ def createBitMapping( if printMappings or verbose: if parity: print( - "init.mem[{}][{}] -> {}.{}_Y{}.INITP_{:02x}[{:03}]" - .format( - w, b, cell.tile, - cell.type[:-2], y01, initRow, bbb + "init.mem[{}][{}] -> {}.{}_Y{}.INITP_{:02x}[{:03}]". + format( + w, b, cell.tile, cell.type[:-2], y01, initRow, bbb #cell.tile, #hex(cell.baseaddr), segoffset[0], segoffset[1], #cell.wordoffset @@ -208,10 +205,9 @@ def createBitMapping( else: print( - "init.mem[{}][{}] -> {}.{}_Y{}.INIT_{:02x}[{:03}]" - .format( - w, b, cell.tile, - cell.type[:-2], y01, initRow, bbb + "init.mem[{}][{}] -> {}.{}_Y{}.INIT_{:02x}[{:03}]". + format( + w, b, cell.tile, cell.type[:-2], y01, initRow, bbb #cell.tile, #hex(cell.baseaddr), segoffset[0], segoffset[1], #cell.wordoffset @@ -219,7 +215,7 @@ def createBitMapping( ) # 2.j1: Compute xyz (7 series) - xyz = initRow * 512 + 2*bbb + y01 + xyz = initRow * 512 + 2 * bbb + y01 xyz = xyz + 32768 if parity else xyz # 2.k: Finally, build a Mapping object and add it to the mappings list (to be returned below) @@ -321,12 +317,7 @@ def findSegOffset(segs, lr, y01, initinitp, initnum, initbit): ############################################################################################## # Create the bitmappings for a design ############################################################################################## -def createBitMappings( - memName, - mddName, - verbose, - printMappings -): +def createBitMappings(memName, mddName, verbose, printMappings): # 1. Load the MDD file. mdd_data = parse_mdd.readAndFilterMDDData(mddName, memName) @@ -382,8 +373,7 @@ def mapSort(m): baseDir = pathlib.Path(args.baseDir).resolve() mappings = createBitMappings( - args.memname, baseDir / args.mddname, args.verbose, - args.printmappings + args.memname, baseDir / args.mddname, args.verbose, args.printmappings ) # Since this is a test program, print out what was returned diff --git a/bits2init.py b/bits2init.py new file mode 100644 index 0000000..1113b95 --- /dev/null +++ b/bits2init.py @@ -0,0 +1,126 @@ +import os +import sys +import parseutil +import parseutil.misc as misc +import argparse +import pathlib +import DbgParser +import bitMapping +import patch_mem + + +# Check the bits for a complete memory +def bits2init( + baseDir, # pathlib.Path + memName, # str + mdd, # pathlib.Path + initFile, # pathlib.Path + origInitFile, # if not None then will do checking between it and re-created initFile on the previous line + fasmFile, # pathlib.Path + verbose, # bool + printmappings # bool +): + designName = baseDir.name + + # 0. Read the MDD data and filter out the ones we want for this memory + mdd_data = patch_mem.readAndFilterMDDData(mdd, memName) + words, initbitwidth = misc.getMDDMemorySize(mdd_data) + + # 1. Get the mapping info + print("Loading mappings for {}...".format(designName)) + mappings = bitMapping.createBitMappings( + baseDir, # The directory where the design lives + memName, + mdd, + False, + printmappings + ) + print(" Done loading mappings") + + # 2. Get the frames + frames = DbgParser.loadFrames( + baseDir / "vivado" / "{}.bit".format(designName) + ) + + # 3. Make arrays to hold the new init data + initArrays = [[None for j in range(initbitwidth)] for k in range(words)] + initStrings = [None for j in range(words)] + + # 4. Use mappings to take the frame data, and make ordered arrays of data + print("Assembling init strings for {}".format(designName)) + for mapping in mappings: + frameWord = int(mapping.frameBitOffset / 32) + frameBit = mapping.frameBitOffset % 32 + binaryWord = bin(frames[mapping.frameAddr][frameWord])[2:] + binaryWord = ('0' * (32 - len(binaryWord))) + binaryWord + binaryWord = binaryWord[::-1] + initArrays[mapping.word][mapping.bit] = binaryWord[frameBit] + + # 5. Combine the arrays into new init strings + for i in range(words): + string = "".join(initArrays[i]) + string = string[::-1] + initStrings[i] = string + + # 5a. Check the new strings against existing .mem files + # Only checks if the --check flag was set + if origInitFile is not None: + print(" Checking with original...") + origInit = parseutil.parse_init_test.read_initfile( + origInitFile, initbitwidth, reverse=False + ) + for w in range(words): + for b in range(initbitwidth): + if initStrings[w][b] != origInit[w][b]: + print( + "Mismatch: {}:{} {} {}".format( + w, b, initStrings[w][b], origInit[w][b] + ) + ) + print( + "original: {}\nnew: {}".format( + hex(int(origInit[w], 2)), + hex(int(initStrings[w], 2)) + ) + ) + sys.exit(1) + print(" Everything checked out successfully!!!") + print(" Done assembling init strings") + print("Writing to {}/init/new.mem".format(designName)) + + # 6. Writes the string to new.mem in the init directory of a design + with (baseDir / "init" / "new.mem").open('w') as f: + for string in initStrings: + f.write(hex(int(string, 2))[2:]) + f.write("\n") + print(" Done writing file") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "baseDir", help='Directory where design sub-directories are located.' + ) + + parser.add_argument( + "memname", help='Name of memory to check (as in "mem/ram")' + ) + parser.add_argument("mddname", help='Name of mdd file)') + parser.add_argument("--verbose", action='store_true') + parser.add_argument("--check", action='store_true') + parser.add_argument( + "--printmappings", action='store_true', help='Print the mapping info' + ) + args = parser.parse_args() + + baseDir = pathlib.Path(args.baseDir).resolve() + designName = baseDir.name + + bits2init( + baseDir, args.memname, baseDir / args.mddname, + baseDir / "init/fromFasm.mem", + baseDir / "init/init.mem" if args.check == True else None, + baseDir / "real.fasm", args.verbose, args.printmappings + ) + + print("") diff --git a/bits2init_all.py b/bits2init_all.py new file mode 100644 index 0000000..3710766 --- /dev/null +++ b/bits2init_all.py @@ -0,0 +1,45 @@ +import checkTheBits +import argparse +import pathlib +import bits2init + + +def designSizes(designName): + words = designName.split('b')[0] + if words[-1] == 'k': + words = int(words[:-1]) * 1024 + else: + words = int(words) + bits = int(designName.split('b')[1]) + return (words, bits) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "baseDir", help='Directory where design sub-directories are located.' + ) + + parser.add_argument("--verbose", action='store_true') + + parser.add_argument( + "--printmappings", action='store_true', help='Print the mapping info' + ) + + args = parser.parse_args() + + baseDir = pathlib.Path(args.baseDir).resolve() + dirs = list(baseDir.glob("*")) + dirs.sort() + + for d in dirs: + designName = d.name + words, bits = designSizes(designName) + print(designName) + bits2init.bits2init( + d, "mem/ram", d / "{}.mdd".format(designName), d / "init/new.mem", + d / "init/init.mem", d / "real.fasm", args.verbose, + args.printmappings + ) + print("") + print("") diff --git a/init2fasm.py b/init2fasm.py new file mode 100644 index 0000000..ae81642 --- /dev/null +++ b/init2fasm.py @@ -0,0 +1,203 @@ +import pathlib +import argparse +import bitMapping +import patch_mem +import parseutil.misc as misc +import re + + +def create_dictionary(mdd_data): + output_dict = {} + for data in mdd_data: + output_dict[data.tile] = { + 'Y0INIT': [], + 'Y1INIT': [], + 'Y0INITP': [], + 'Y1INITP': [] + } + return output_dict + + +def init2fasm( + baseDir, # pathlib.Path + memName, # str + mdd, # pathlib.Path + initFile, # pathlib.Path + fasmFile, # pathlib.Path + checkFile, #pathlib.Path + verbose, # bool + printmappings, # bool + partial # bool +): + designName = baseDir.name + + # 0. Read the MDD data and filter out the ones we want for this memory + mdd_data = patch_mem.readAndFilterMDDData(mdd, memName) + words, initbitwidth = misc.getMDDMemorySize(mdd_data) + + reassembled_init_array = create_dictionary(mdd_data) + reassembled_init_strings = create_dictionary(mdd_data) + + # 1. Get the mapping info + print("Loading mappings for {}...".format(designName)) + mappings = bitMapping.createBitMappings( + baseDir, # The directory where the design lives + memName, + mdd, + False, + printmappings + ) + print(" Done loading mappings") + + # 2. Get the init data + with initFile.open() as f: + init_words = f.read().split() + + # 3. Reassemble init strings as a dictionary of arrays + print("Assembling new FASM strings from {}".format(initFile.name)) + for mapping in mappings: + if mapping.fasmY: + index_string = 'Y1' + else: + index_string = 'Y0' + if mapping.fasmINITP: + index_string += 'INITP' + else: + index_string += 'INIT' + while len(reassembled_init_array[mapping.tile][index_string] + ) <= mapping.fasmLine: + reassembled_init_array[mapping.tile][index_string].append( + [None] * 256 + ) + bin_word = (bin(int(init_words[mapping.word], 16))[2:])[::-1] + if mapping.bit >= len(bin_word): + reassembled_init_array[mapping.tile][index_string][ + mapping.fasmLine][mapping.fasmBit] = '0' + else: + reassembled_init_array[mapping.tile][index_string][ + mapping.fasmLine][mapping.fasmBit] = bin_word[mapping.bit] + + # 4. Combine reassembled init arrays into strings + for tile in reassembled_init_array: + for group in reassembled_init_array[tile]: + for line in reassembled_init_array[tile][group]: + for i in range(len(line)): + if line[i] == None: + line[i] = '0' + full_word = ("".join(line))[::-1] + reassembled_init_strings[tile][group].append( + full_word[full_word.index('1'):] + ) + print(" Done assembling new fasm init strings") + + # 5. Get the base fasm data to edit later + with fasmFile.open() as f: + fasm_lines = f.readlines() + + # 6. Replace fasm init lines with newly constructed ones + print("Editing fasm lines") + for tile in reassembled_init_strings: + for group in reassembled_init_strings[tile]: + for i in range(len(reassembled_init_strings[tile][group])): + string = reassembled_init_strings[tile][group][i] + fasm_num = hex(i)[2:] + k = -1 + for j in range(len(fasm_lines)): + if re.search(tile + "\.RAMB18_" + group[0:2] + "\." + + group[2:] + "_0?" + fasm_num.upper() + "\[", + fasm_lines[j]) != None: + k = j + break + new_fasm_line = "{}.RAMB18_{}.{}_{}{}[{}:0] = {}'b{}\n".format( + tile, group[0:2], group[2:], + "" if len(fasm_num) == 2 else "0", fasm_num.upper(), + str(len(string) - 1), len(string), string + ) + if k != -1: + fasm_lines[k] = new_fasm_line + else: + fasm_int = int(fasm_num, 16) + for j in range(len(fasm_lines)): + if re.search(tile + "\.RAMB18_" + group[0:2] + "\." + + group[2:] + "_", fasm_lines[j]) != None: + if fasm_int == 0: + fasm_lines.insert(j, new_fasm_line) + break + if fasm_int > int(re.search( + "_..\[", fasm_lines[j]).group(0)[1:3], 16): + entry_group = re.search( + tile + "\.RAMB18_" + group[0:2] + "\." + + group[2:] + "_..", fasm_lines[j + 1] + ) + if entry_group == None: + fasm_lines.insert(j + 1, new_fasm_line) + break + entry_num = int(entry_group.group(0)[-2:], 16) + if fasm_int < entry_num: + fasm_lines.insert(j + 1, new_fasm_line) + break + print(" Done editing fasm lines") + + # 7. Write the new lines out to new.fasm + with (baseDir / "new.fasm").open('w') as w: + if partial: + current_tile = "" + for line in fasm_lines: + for data in mdd_data: + if re.search(data.tile, line) != None: + if current_tile != "" and data.tile != current_tile: + w.write("\n") + w.write(line) + current_tile = data.tile + break + else: + for line in fasm_lines: + w.write(line) + + # 8. Check the new lines against real.fasm + if checkFile != None: + print("Checking new fasm lines against real.fasm") + with checkFile.open() as f: + check_lines = f.readlines() + if len(check_lines) != len(fasm_lines): + print( + " There is a different number of fasm lines in the original and new file" + ) + exit(1) + for i in range(len(check_lines)): + if check_lines[i] != fasm_lines[i]: + print(" Mismatch on line {}".format(i + 1)) + print(" Expected: {}".format(check_lines[i])) + print(" Actual: {}".format(fasm_lines[i])) + exit(1) + print(" Everything matches") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "baseDir", help='Directory where design sub-directories are located.' + ) + + parser.add_argument( + "memname", help='Name of memory to check (as in "mem/ram")' + ) + parser.add_argument("mddname", help='Name of mdd file)') + parser.add_argument("memfile", help='Name of the mem file to use') + parser.add_argument("--verbose", action='store_true') + parser.add_argument("--check", action='store_true') + parser.add_argument( + "--printmappings", action='store_true', help='Print the mapping info' + ) + parser.add_argument("--partial", action='store_true') + args = parser.parse_args() + + baseDir = pathlib.Path(args.baseDir).resolve() + designName = baseDir.name + + init2fasm( + baseDir, args.memname, baseDir / args.mddname, baseDir / args.memfile, + baseDir / "real.fasm", + baseDir / "real.fasm" if args.check == True else None, args.verbose, + args.printmappings, args.partial + ) diff --git a/init2fasm_all.py b/init2fasm_all.py new file mode 100644 index 0000000..06dfb32 --- /dev/null +++ b/init2fasm_all.py @@ -0,0 +1,30 @@ +import init2fasm +import argparse +import pathlib + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "baseDir", help='Directory where design sub-directories are located.' + ) + + parser.add_argument("--verbose", action='store_true') + + parser.add_argument( + "--printmappings", action='store_true', help='Print the mapping info' + ) + + args = parser.parse_args() + + baseDir = pathlib.Path(args.baseDir).resolve() + dirs = list(baseDir.glob("*")) + dirs.sort() + + for d in dirs: + designName = d.name + init2fasm.init2fasm( + d, "mem/ram", d / "{}.mdd".format(designName), d / "init/init.mem", + d / "real.fasm", d / "real.fasm", args.verbose, args.printmappings, + False + ) + print("") diff --git a/parseutil/parse_mdd.py b/parseutil/parse_mdd.py index 4aa9bcb..21aee65 100644 --- a/parseutil/parse_mdd.py +++ b/parseutil/parse_mdd.py @@ -44,6 +44,7 @@ def toString(self): ) return s + def readAndFilterMDDData(mdd, selectedMemToPatch, verbose=False): # Handles either Path or strings if isinstance(mdd, pathlib.Path): diff --git a/patch_mem.py b/patch_mem.py index 1479c4e..634e5d5 100644 --- a/patch_mem.py +++ b/patch_mem.py @@ -12,8 +12,6 @@ from prjxray import fasm_disassembler - - def patch_mem( fasm=None, init=None, @@ -56,13 +54,11 @@ def patch_mem( # new memory tuples to create a partial FASM file merged = merge_tuples(cleared_tups=frame_tups, mem_tups=memfasm) write_fasm(outfile, merged) - print("In partial") else: # Merge all non-INIT tuples (cleared_tups) in with the new memory tuples # to create a new complete FASM file merged = merge_tuples(cleared_tups=cleared_tups, mem_tups=memfasm) write_fasm(outfile, merged) - print("We ain't in Kansas no more") print("Patching done...")