mirror of https://github.com/openXC7/prjxray.git
Merge pull request #1186 from antmicro/in_term_group
Grouping of IN_TERM features
This commit is contained in:
commit
c0289c5948
|
|
@ -13,7 +13,7 @@ build/segbits_xiob33.rdb: $(SPECIMENS_OK)
|
||||||
|
|
||||||
build/segbits_xiob33.db: build/segbits_xiob33.rdb process_rdb.py bits.dbf
|
build/segbits_xiob33.db: build/segbits_xiob33.rdb process_rdb.py bits.dbf
|
||||||
python3 process_rdb.py build/segbits_xiob33.rdb > build/segbits_xiob33_processed.rdb
|
python3 process_rdb.py build/segbits_xiob33.rdb > build/segbits_xiob33_processed.rdb
|
||||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in build/segbits_xiob33_processed.rdb --seg-fn-out $@
|
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --groups tag_groups.txt --seg-fn-in build/segbits_xiob33_processed.rdb --seg-fn-out $@
|
||||||
${XRAY_MASKMERGE} build/mask_xiob33.db $$(find -name segdata_liob33.txt) $$(find -name segdata_riob33.txt)
|
${XRAY_MASKMERGE} build/mask_xiob33.db $$(find -name segdata_liob33.txt) $$(find -name segdata_riob33.txt)
|
||||||
|
|
||||||
build/segbits_hclk_ioi3.rdb: $(SPECIMENS_OK)
|
build/segbits_hclk_ioi3.rdb: $(SPECIMENS_OK)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
38_92 39_93 38_94,IOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
|
||||||
38_106 39_107 39_111 38_106 38_110 39_105 39_109,IOB33.IOB_Y0.SLEW.FAST
|
|
||||||
39_33 38_34 39_35,IOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
|
||||||
39_21 38_16 38_20 38_18 38_22 39_17,IOB33.IOB_Y1.SLEW.FAST
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
IOB33.IOB_Y0.IN_TERM.NONE IOB33.IOB_Y0.IN_TERM.UNTUNED_SPLIT_40 IOB33.IOB_Y0.IN_TERM.UNTUNED_SPLIT_50 IOB33.IOB_Y0.IN_TERM.UNTUNED_SPLIT_60
|
||||||
|
IOB33.IOB_Y1.IN_TERM.NONE IOB33.IOB_Y1.IN_TERM.UNTUNED_SPLIT_40 IOB33.IOB_Y1.IN_TERM.UNTUNED_SPLIT_50 IOB33.IOB_Y1.IN_TERM.UNTUNED_SPLIT_60
|
||||||
|
|
||||||
|
IOB33.IOB_Y0.PULLTYPE.KEEPER IOB33.IOB_Y0.PULLTYPE.NONE IOB33.IOB_Y0.PULLTYPE.PULLDOWN IOB33.IOB_Y0.PULLTYPE.PULLUP
|
||||||
|
IOB33.IOB_Y1.PULLTYPE.KEEPER IOB33.IOB_Y1.PULLTYPE.NONE IOB33.IOB_Y1.PULLTYPE.PULLDOWN IOB33.IOB_Y1.PULLTYPE.PULLUP
|
||||||
234
utils/dbfixup.py
234
utils/dbfixup.py
|
|
@ -1,6 +1,7 @@
|
||||||
#/usr/bin/env python3
|
#/usr/bin/env python3
|
||||||
|
|
||||||
import sys, os, re
|
import sys, os, re
|
||||||
|
import itertools
|
||||||
from prjxray import util
|
from prjxray import util
|
||||||
|
|
||||||
clb_int_zero_db = [
|
clb_int_zero_db = [
|
||||||
|
|
@ -199,7 +200,30 @@ class ZeroGroups(object):
|
||||||
bits.add("!" + bit)
|
bits.add("!" + bit)
|
||||||
|
|
||||||
|
|
||||||
def add_zero_bits(fn_in, zero_db, clb_int=False, strict=True, verbose=False):
|
def read_segbits(fn_in):
|
||||||
|
"""
|
||||||
|
Reads a segbits file. Removes duplcated lines. Returns a list of the lines.
|
||||||
|
"""
|
||||||
|
lines = []
|
||||||
|
llast = None
|
||||||
|
|
||||||
|
with open(fn_in, "r") as f:
|
||||||
|
for line in f:
|
||||||
|
# Hack: skip duplicate lines
|
||||||
|
# This happens while merging a new multibit entry
|
||||||
|
line = line.strip()
|
||||||
|
if len(line) == 0:
|
||||||
|
continue
|
||||||
|
if line == llast:
|
||||||
|
continue
|
||||||
|
|
||||||
|
lines.append(line)
|
||||||
|
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def add_zero_bits(
|
||||||
|
fn_in, lines, zero_db, clb_int=False, strict=True, verbose=False):
|
||||||
'''
|
'''
|
||||||
Add multibit entries
|
Add multibit entries
|
||||||
This requires adding some zero bits (ex: !31_09)
|
This requires adding some zero bits (ex: !31_09)
|
||||||
|
|
@ -208,27 +232,17 @@ def add_zero_bits(fn_in, zero_db, clb_int=False, strict=True, verbose=False):
|
||||||
|
|
||||||
zero_groups = ZeroGroups(zero_db)
|
zero_groups = ZeroGroups(zero_db)
|
||||||
|
|
||||||
lines = []
|
|
||||||
new_lines = set()
|
new_lines = set()
|
||||||
changes = 0
|
changes = 0
|
||||||
|
|
||||||
llast = None
|
|
||||||
drops = 0
|
drops = 0
|
||||||
|
|
||||||
with open(fn_in, "r") as f:
|
for line in lines:
|
||||||
for line in f:
|
|
||||||
# Hack: skip duplicate lines
|
|
||||||
# This happens while merging a new multibit entry
|
|
||||||
line = line.strip()
|
|
||||||
if line == llast:
|
|
||||||
continue
|
|
||||||
|
|
||||||
lines.append(line)
|
tag, bits, mode, _ = util.parse_db_line(line)
|
||||||
|
|
||||||
tag, bits, mode, _ = util.parse_db_line(line)
|
if bits is not None and mode is None:
|
||||||
|
zero_groups.add_tag_bits(tag, bits)
|
||||||
if bits is not None and mode is None:
|
|
||||||
zero_groups.add_tag_bits(tag, bits)
|
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
zero_groups.print_groups()
|
zero_groups.print_groups()
|
||||||
|
|
@ -366,7 +380,7 @@ def remove_ambiguous_solutions(fn_in, db_lines, strict=True, verbose=True):
|
||||||
return 0, db_lines
|
return 0, db_lines
|
||||||
|
|
||||||
drops = 0
|
drops = 0
|
||||||
output_lines = []
|
output_lines = set()
|
||||||
|
|
||||||
for l in db_lines:
|
for l in db_lines:
|
||||||
parts = l.split()
|
parts = l.split()
|
||||||
|
|
@ -374,7 +388,7 @@ def remove_ambiguous_solutions(fn_in, db_lines, strict=True, verbose=True):
|
||||||
bits = frozenset(parts[1:])
|
bits = frozenset(parts[1:])
|
||||||
|
|
||||||
if bits not in dropped_solutions:
|
if bits not in dropped_solutions:
|
||||||
output_lines.append(l)
|
output_lines.add(l)
|
||||||
drops += 1
|
drops += 1
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
|
|
@ -387,8 +401,81 @@ def remove_ambiguous_solutions(fn_in, db_lines, strict=True, verbose=True):
|
||||||
return drops, output_lines
|
return drops, output_lines
|
||||||
|
|
||||||
|
|
||||||
|
def group_tags(lines, tag_groups, bit_groups):
|
||||||
|
"""
|
||||||
|
Implements tag grouping. If a tag belongs to a group then the common bits
|
||||||
|
of that group are added to is as zeros.
|
||||||
|
|
||||||
|
>>> tg = [{"A", "B"}]
|
||||||
|
>>> bg = [{(1, 2), (3, 4)}]
|
||||||
|
>>> res = group_tags({"A 1_2", "B 3_4"}, tg, bg)
|
||||||
|
>>> (res[0], sorted(list(res[1])))
|
||||||
|
(2, ['A 1_2 !3_4', 'B !1_2 3_4'])
|
||||||
|
|
||||||
|
>>> tg = [{"A", "B"}]
|
||||||
|
>>> bg = [{(1, 2), (3, 4)}]
|
||||||
|
>>> res = group_tags({"A 1_2", "B 3_4", "C 1_2"}, tg, bg)
|
||||||
|
>>> (res[0], sorted(list(res[1])))
|
||||||
|
(2, ['A 1_2 !3_4', 'B !1_2 3_4', 'C 1_2'])
|
||||||
|
"""
|
||||||
|
|
||||||
|
changes = 0
|
||||||
|
new_lines = set()
|
||||||
|
|
||||||
|
# Process lines
|
||||||
|
for line in lines:
|
||||||
|
|
||||||
|
line = line.strip()
|
||||||
|
if not len(line):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Parse the line
|
||||||
|
tag, bits, mode, _ = util.parse_db_line(line)
|
||||||
|
if not bits:
|
||||||
|
bits = set()
|
||||||
|
else:
|
||||||
|
bits = set([util.parse_tagbit(b) for b in bits])
|
||||||
|
|
||||||
|
# Check if the tag belongs to a group
|
||||||
|
for tag_group, bit_group in zip(tag_groups, bit_groups):
|
||||||
|
if tag in tag_group:
|
||||||
|
|
||||||
|
# Add zero bits to the tag if not already there
|
||||||
|
bit_coords = set([b[1] for b in bits])
|
||||||
|
for zero_bit in bit_group:
|
||||||
|
if zero_bit not in bit_coords:
|
||||||
|
bits.add((False, zero_bit))
|
||||||
|
|
||||||
|
# Format the line
|
||||||
|
bit_strs = []
|
||||||
|
for bit in sorted(list(bits), key=lambda b: b[1]):
|
||||||
|
s = "!" if not bit[0] else ""
|
||||||
|
s += "{}_{}".format(bit[1][0], bit[1][1])
|
||||||
|
bit_strs.append(s)
|
||||||
|
|
||||||
|
new_line = " ".join([tag] + bit_strs)
|
||||||
|
|
||||||
|
# Add the line
|
||||||
|
new_lines.add(new_line)
|
||||||
|
changes += 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# It does not, pass it through unchanged
|
||||||
|
else:
|
||||||
|
new_lines.add(line)
|
||||||
|
|
||||||
|
return changes, new_lines
|
||||||
|
|
||||||
|
|
||||||
def update_seg_fns(
|
def update_seg_fns(
|
||||||
fn_inouts, zero_db, clb_int, lazy=False, strict=True, verbose=False):
|
fn_inouts,
|
||||||
|
zero_db,
|
||||||
|
tag_groups,
|
||||||
|
clb_int,
|
||||||
|
lazy=False,
|
||||||
|
strict=True,
|
||||||
|
verbose=False):
|
||||||
|
|
||||||
seg_files = 0
|
seg_files = 0
|
||||||
seg_lines = 0
|
seg_lines = 0
|
||||||
for fn_in, fn_out in fn_inouts:
|
for fn_in, fn_out in fn_inouts:
|
||||||
|
|
@ -396,20 +483,35 @@ def update_seg_fns(
|
||||||
if lazy and not os.path.exists(fn_in):
|
if lazy and not os.path.exists(fn_in):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
changes, new_lines = add_zero_bits(
|
lines = read_segbits(fn_in)
|
||||||
fn_in, zero_db, clb_int=clb_int, strict=strict, verbose=verbose)
|
changes = 0
|
||||||
|
|
||||||
new_changes, final_lines = remove_ambiguous_solutions(
|
# Find common bits for tag groups
|
||||||
|
bit_groups = find_common_bits_for_tag_groups(lines, tag_groups)
|
||||||
|
|
||||||
|
# Group tags
|
||||||
|
new_changes, lines = group_tags(lines, tag_groups, bit_groups)
|
||||||
|
changes += new_changes
|
||||||
|
|
||||||
|
new_changes, lines = add_zero_bits(
|
||||||
fn_in,
|
fn_in,
|
||||||
new_lines,
|
lines,
|
||||||
|
zero_db,
|
||||||
|
clb_int=clb_int,
|
||||||
|
strict=strict,
|
||||||
|
verbose=verbose)
|
||||||
|
changes += new_changes
|
||||||
|
|
||||||
|
new_changes, lines = remove_ambiguous_solutions(
|
||||||
|
fn_in,
|
||||||
|
lines,
|
||||||
strict=strict,
|
strict=strict,
|
||||||
verbose=verbose,
|
verbose=verbose,
|
||||||
)
|
)
|
||||||
|
|
||||||
changes += new_changes
|
changes += new_changes
|
||||||
|
|
||||||
with open(fn_out, "w") as f:
|
with open(fn_out, "w") as f:
|
||||||
for line in sorted(final_lines):
|
for line in sorted(lines):
|
||||||
print(line, file=f)
|
print(line, file=f)
|
||||||
|
|
||||||
if changes is not None:
|
if changes is not None:
|
||||||
|
|
@ -453,6 +555,7 @@ def update_segs(
|
||||||
seg_fn_in,
|
seg_fn_in,
|
||||||
seg_fn_out,
|
seg_fn_out,
|
||||||
zero_db_fn,
|
zero_db_fn,
|
||||||
|
tag_groups,
|
||||||
strict=True,
|
strict=True,
|
||||||
verbose=False):
|
verbose=False):
|
||||||
if clb_int:
|
if clb_int:
|
||||||
|
|
@ -479,7 +582,72 @@ def update_segs(
|
||||||
print("CLB INT mode: %s" % clb_int)
|
print("CLB INT mode: %s" % clb_int)
|
||||||
print("Segbit groups: %s" % len(zero_db))
|
print("Segbit groups: %s" % len(zero_db))
|
||||||
update_seg_fns(
|
update_seg_fns(
|
||||||
fn_inouts, zero_db, clb_int, lazy=lazy, strict=strict, verbose=verbose)
|
fn_inouts,
|
||||||
|
zero_db,
|
||||||
|
tag_groups,
|
||||||
|
clb_int,
|
||||||
|
lazy=lazy,
|
||||||
|
strict=strict,
|
||||||
|
verbose=verbose)
|
||||||
|
|
||||||
|
|
||||||
|
def find_common_bits_for_tag_groups(lines, tag_groups):
|
||||||
|
"""
|
||||||
|
For each tag group finds a common set of bits that have value of one.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bit_groups = []
|
||||||
|
|
||||||
|
for tag_group in tag_groups:
|
||||||
|
bit_group = set()
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
tag, bits, mode, _ = util.parse_db_line(line)
|
||||||
|
if not bits:
|
||||||
|
continue
|
||||||
|
|
||||||
|
bits = set([util.parse_tagbit(b) for b in bits])
|
||||||
|
|
||||||
|
if tag in tag_group and len(bits):
|
||||||
|
ones = set([b[1] for b in bits if b[0]])
|
||||||
|
bit_group |= ones
|
||||||
|
|
||||||
|
bit_groups.append(bit_group)
|
||||||
|
|
||||||
|
return bit_groups
|
||||||
|
|
||||||
|
|
||||||
|
def load_tag_groups(file_name):
|
||||||
|
"""
|
||||||
|
Loads tag groups from a text file.
|
||||||
|
|
||||||
|
A tag group is defined by specifying a space separated list of tags within
|
||||||
|
a single line. Lines that are empty or start with '#' are ignored.
|
||||||
|
"""
|
||||||
|
tag_groups = []
|
||||||
|
|
||||||
|
# Load tag group specifications
|
||||||
|
with open(file_name, "r") as fp:
|
||||||
|
for line in fp:
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if len(line) == 0 or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
group = set(line.split())
|
||||||
|
if len(group):
|
||||||
|
tag_groups.append(group)
|
||||||
|
|
||||||
|
# Check if all tag groups are exclusive
|
||||||
|
for tag_group_a, tag_group_b in itertools.combinations(tag_groups, 2):
|
||||||
|
|
||||||
|
tags = tag_group_a & tag_group_b
|
||||||
|
if len(tags):
|
||||||
|
raise RuntimeError(
|
||||||
|
"Tag(s) {} are present in multiple groups".format(
|
||||||
|
" ".join(tags)))
|
||||||
|
|
||||||
|
return tag_groups
|
||||||
|
|
||||||
|
|
||||||
def run(
|
def run(
|
||||||
|
|
@ -488,12 +656,18 @@ def run(
|
||||||
zero_db_fn=None,
|
zero_db_fn=None,
|
||||||
seg_fn_in=None,
|
seg_fn_in=None,
|
||||||
seg_fn_out=None,
|
seg_fn_out=None,
|
||||||
|
groups_fn_in=None,
|
||||||
strict=None,
|
strict=None,
|
||||||
verbose=False):
|
verbose=False):
|
||||||
|
|
||||||
if strict is None:
|
if strict is None:
|
||||||
strict = not clb_int
|
strict = not clb_int
|
||||||
|
|
||||||
|
# Load tag groups
|
||||||
|
tag_groups = []
|
||||||
|
if groups_fn_in is not None:
|
||||||
|
tag_groups = load_tag_groups(groups_fn_in)
|
||||||
|
|
||||||
# Probably should split this into two programs
|
# Probably should split this into two programs
|
||||||
update_segs(
|
update_segs(
|
||||||
db_root,
|
db_root,
|
||||||
|
|
@ -501,6 +675,7 @@ def run(
|
||||||
seg_fn_in=seg_fn_in,
|
seg_fn_in=seg_fn_in,
|
||||||
seg_fn_out=seg_fn_out,
|
seg_fn_out=seg_fn_out,
|
||||||
zero_db_fn=zero_db_fn,
|
zero_db_fn=zero_db_fn,
|
||||||
|
tag_groups=tag_groups,
|
||||||
strict=strict,
|
strict=strict,
|
||||||
verbose=verbose)
|
verbose=verbose)
|
||||||
if clb_int:
|
if clb_int:
|
||||||
|
|
@ -520,6 +695,14 @@ def main():
|
||||||
parser.add_argument('--seg-fn-in', help='')
|
parser.add_argument('--seg-fn-in', help='')
|
||||||
parser.add_argument('--seg-fn-out', help='')
|
parser.add_argument('--seg-fn-out', help='')
|
||||||
util.add_bool_arg(parser, "--strict", default=False)
|
util.add_bool_arg(parser, "--strict", default=False)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-g",
|
||||||
|
"--groups",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="Input tag group definition file")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
run(
|
run(
|
||||||
|
|
@ -528,6 +711,7 @@ def main():
|
||||||
args.zero_db,
|
args.zero_db,
|
||||||
args.seg_fn_in,
|
args.seg_fn_in,
|
||||||
args.seg_fn_out,
|
args.seg_fn_out,
|
||||||
|
args.groups,
|
||||||
strict=args.strict,
|
strict=args.strict,
|
||||||
verbose=args.verbose)
|
verbose=args.verbose)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,220 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
|
||||||
|
This script Reads tag group definition from a file and applies the tag grouping.
|
||||||
|
First a set of common bits for each group is found (logical OR among all tags
|
||||||
|
belonging to the group). Then in each tag belonging to the group those bits are
|
||||||
|
set to 0 but only if they are not already present there.
|
||||||
|
|
||||||
|
The resulting data is written into a segbits file.
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def load_tag_groups(file_name):
|
||||||
|
"""
|
||||||
|
Loads tag groups from a text file.
|
||||||
|
|
||||||
|
A tag group is defined by specifying a space separated list of tags within
|
||||||
|
a single line. Lines that are empty or start with '#' are ignored.
|
||||||
|
"""
|
||||||
|
tag_groups = []
|
||||||
|
|
||||||
|
# Load tag group specifications
|
||||||
|
with open(file_name, "r") as fp:
|
||||||
|
for line in fp:
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if len(line) == 0 or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
group = set(line.split())
|
||||||
|
if len(group):
|
||||||
|
tag_groups.append(group)
|
||||||
|
|
||||||
|
# Check if all tag groups are exclusive
|
||||||
|
for tag_group_a, tag_group_b in itertools.combinations(tag_groups, 2):
|
||||||
|
|
||||||
|
tags = tag_group_a & tag_group_b
|
||||||
|
if len(tags):
|
||||||
|
raise RuntimeError(
|
||||||
|
"Tag(s) {} are present in multiple groups".format(
|
||||||
|
" ".join(tags)))
|
||||||
|
|
||||||
|
return tag_groups
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def parse_bit(bit):
|
||||||
|
"""
|
||||||
|
Decodes string describing a bit. Returns a tuple (frame, bit, value)
|
||||||
|
"""
|
||||||
|
match = re.match("^(!?)([0-9]+)_([0-9]+)$", bit)
|
||||||
|
assert match != None, bit
|
||||||
|
|
||||||
|
val = int(match.group(1) != "!")
|
||||||
|
frm = int(match.group(2))
|
||||||
|
bit = int(match.group(3))
|
||||||
|
|
||||||
|
return frm, bit, val
|
||||||
|
|
||||||
|
|
||||||
|
def bit_to_str(bit):
|
||||||
|
"""
|
||||||
|
Converts a tuple (frame, bit, value) to its string representation.
|
||||||
|
"""
|
||||||
|
s = "!" if not bit[2] else ""
|
||||||
|
return "{}{}_{:02d}".format(s, bit[0], bit[1])
|
||||||
|
|
||||||
|
|
||||||
|
def load_segbits(file_name):
|
||||||
|
"""
|
||||||
|
Loads a segbits file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
segbits = {}
|
||||||
|
|
||||||
|
with open(file_name, "r") as fp:
|
||||||
|
for line in fp:
|
||||||
|
line = line.strip()
|
||||||
|
fields = line.split()
|
||||||
|
|
||||||
|
if len(fields) < 2:
|
||||||
|
raise RuntimeError("Malformed line: '%s'" % line)
|
||||||
|
|
||||||
|
tag = fields[0]
|
||||||
|
|
||||||
|
if "<" in line or ">" in line:
|
||||||
|
segbits[tag] = " ".join(fields[1:])
|
||||||
|
|
||||||
|
else:
|
||||||
|
bits = set([parse_bit(bit) for bit in fields[1:]])
|
||||||
|
segbits[tag] = bits
|
||||||
|
|
||||||
|
return segbits
|
||||||
|
|
||||||
|
|
||||||
|
def save_segbits(file_name, segbits):
|
||||||
|
"""
|
||||||
|
Save segbits to a .db or .rdb file
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(file_name, "w") as fp:
|
||||||
|
for tag, bits in segbits.items():
|
||||||
|
|
||||||
|
if isinstance(bits, str):
|
||||||
|
line = tag + " " + bits
|
||||||
|
|
||||||
|
elif isinstance(bits, set):
|
||||||
|
line = tag + " "
|
||||||
|
line += " ".join(
|
||||||
|
[bit_to_str(bit) for bit in sorted(list(bits))])
|
||||||
|
|
||||||
|
fp.write(line + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def mask_out_bits(segbits, mask, tags_to_mask=None):
|
||||||
|
"""
|
||||||
|
Given a set of bits and a list of tags to affect (optional) removes all
|
||||||
|
the bits from each tag that are present (and equal) in the masking set.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if tags_to_mask is None:
|
||||||
|
tags_to_mask = segbits.keys()
|
||||||
|
|
||||||
|
# Mask out matching bits
|
||||||
|
for tag in tags_to_mask:
|
||||||
|
bits = segbits[tag]
|
||||||
|
|
||||||
|
bits = set(bits) - set(mask)
|
||||||
|
segbits[tag] = bits
|
||||||
|
|
||||||
|
return segbits
|
||||||
|
|
||||||
|
|
||||||
|
def find_common_bits_for_tag_groups(segbits, tag_groups):
|
||||||
|
"""
|
||||||
|
For each tag group finds a common set of bits that have value of one.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bit_groups = []
|
||||||
|
|
||||||
|
for tag_group in tag_groups:
|
||||||
|
bit_group = set()
|
||||||
|
|
||||||
|
for tag, bits in segbits.items():
|
||||||
|
if tag in tag_group and isinstance(bits, set):
|
||||||
|
ones = set([b for b in bits if b[2]])
|
||||||
|
bit_group |= ones
|
||||||
|
|
||||||
|
bit_groups.append(bit_group)
|
||||||
|
|
||||||
|
return bit_groups
|
||||||
|
|
||||||
|
|
||||||
|
def group_tags(segbits, tag_groups, bit_groups):
|
||||||
|
"""
|
||||||
|
Implements tag grouping. If a tag belongs to a group then the common bits
|
||||||
|
of that group are added to is as zeros.
|
||||||
|
"""
|
||||||
|
|
||||||
|
for tag_group, bit_group in zip(tag_groups, bit_groups):
|
||||||
|
zeros = set([(b[0], b[1], 0) for b in bit_group])
|
||||||
|
for tag in tag_group:
|
||||||
|
|
||||||
|
# Insert zero bits
|
||||||
|
if tag in segbits.keys():
|
||||||
|
bits = segbits[tag]
|
||||||
|
|
||||||
|
if not isinstance(bits, set):
|
||||||
|
bits = set()
|
||||||
|
segbits[tag] = bits
|
||||||
|
|
||||||
|
for z in zeros:
|
||||||
|
if not (z[0], z[1], 1) in bits:
|
||||||
|
bits.add(z)
|
||||||
|
|
||||||
|
return segbits
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
parser.add_argument("-i", required=True, type=str, help="Input .rdb file")
|
||||||
|
parser.add_argument(
|
||||||
|
"-g", required=True, type=str, help="Input tag group definition file")
|
||||||
|
parser.add_argument("-o", required=True, type=str, help="Output .rdb file")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Load tag groups
|
||||||
|
tag_groups = load_tag_groups(args.g)
|
||||||
|
|
||||||
|
# Load raw database file
|
||||||
|
segbits = load_segbits(args.i)
|
||||||
|
|
||||||
|
# Find common bits
|
||||||
|
bit_groups = find_common_bits_for_tag_groups(segbits, tag_groups)
|
||||||
|
# Apply tag grouping
|
||||||
|
segbits = group_tags(segbits, tag_groups, bit_groups)
|
||||||
|
|
||||||
|
# Save fixed database file
|
||||||
|
save_segbits(args.o, segbits)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in New Issue