diff --git a/prjxray/util.py b/prjxray/util.py index 16f28455..7baa127c 100644 --- a/prjxray/util.py +++ b/prjxray/util.py @@ -103,6 +103,23 @@ def parse_db_line(line): return tag, bits, None +def parse_db_lines(fn): + with open(fn, "r") as f: + for line in f: + yield line, parse_db_line(line) + + +def write_db_lines(fn, entries): + new_lines = [] + for tag, bits in entries.items(): + new_line = " ".join([tag] + sorted(bits)) + new_lines.append(new_line) + + with open(fn, "w") as f: + for line in sorted(new_lines): + print(line, file=f) + + def parse_tagbit(x): # !30_07 if x[0] == '!': @@ -186,14 +203,12 @@ def gen_tile_bits(db_root, tilej, strict=False, verbose=False): elif not os.path.exists(fn): continue - with open(fn, "r") as f: - for line in f: - tag, bits, mode = parse_db_line(line) - assert mode is None - for bitstr in bits: - # 31_06 - _bit_inv, (bit_addroff, bit_bitoff) = parse_tagbit(bitstr) - yield (baseaddr + bit_addroff, bitbase + bit_bitoff, tag) + for line, (tag, bits, mode) in parse_db_lines(fn): + assert mode is None + for bitstr in bits: + # 31_06 + _bit_inv, (bit_addroff, bit_bitoff) = parse_tagbit(bitstr) + yield (baseaddr + bit_addroff, bitbase + bit_bitoff, tag) def specn(): diff --git a/utils/groupmask.py b/utils/groupmask.py new file mode 100644 index 00000000..db658ff1 --- /dev/null +++ b/utils/groupmask.py @@ -0,0 +1,81 @@ +#/usr/bin/env python3 + +import sys, os, re +from prjxray import util + + +def index_masks(fn_in, groups_in): + """Return a dictionary with the bits active in each group for the specified list of groups""" + # Only analyze the given groups + groups = {} + for group in groups_in: + groups[group] = set() + + # Index bits + for line, (tag, bits, mode) in util.parse_db_lines(fn_in): + assert not mode, "Unresolved tag: %s" % (line, ) + prefix = tag[0:tag.rfind(".")] + group = groups.get(prefix, None) + # Drop groups we aren't interested in + if group is None: + continue + for bit in bits: + bit = bit.replace("!", "") + group.add(bit) + + # Verify we were able to find all groups + for groupk, groupv in groups.items(): + assert len(groupv), "Bad group %s" % groupk + + return groups + + +def apply_masks(fn_in, groups): + """Add 0 entries ("!") to .db entries based on groups definition""" + new_db = {} + for line, (tag, bits, mode) in util.parse_db_lines(fn_in): + assert not mode, "Unresolved tag: %s" % (line, ) + prefix = tag[0:tag.rfind(".")] + group = groups.get(prefix, None) + if group: + bits = set(bits) + for bit in group: + if bit not in bits: + bits.add("!" + bit) + bits = frozenset(bits) + new_db[tag] = bits + return new_db + + +def load_groups(fn): + ret = [] + for l in open(fn, "r"): + ret.append(l.strip()) + return ret + + +def run(fn_in, fn_out, groups_fn, verbose=False): + groups_in = load_groups(groups_fn) + groups = index_masks(fn_in, groups_in) + new_db = apply_masks(fn_in, groups) + util.write_db_lines(fn_out, new_db) + + +def main(): + import argparse + + parser = argparse.ArgumentParser(description='Create multi-bit entries') + parser.add_argument('--verbose', action='store_true', help='') + parser.add_argument( + '--groups-fn', + default="groups.grp", + help='File containing one group per line to parse') + parser.add_argument('fn_in', help='') + parser.add_argument('fn_out', help='') + args = parser.parse_args() + + run(args.fn_in, args.fn_out, args.groups_fn, verbose=args.verbose) + + +if __name__ == '__main__': + main()