dbfixup: const0 support

Signed-off-by: John McMaster <johndmcmaster@gmail.com>
This commit is contained in:
John McMaster 2018-11-07 18:50:50 -08:00
parent 005616a467
commit dbf2c3b4b2
1 changed files with 126 additions and 84 deletions

View File

@ -21,9 +21,14 @@ def parse_line(line):
parts = line.split() parts = line.split()
# Ex: CLBLL_L.SLICEL_X0.AMUX.A5Q # Ex: CLBLL_L.SLICEL_X0.AMUX.A5Q
tag = parts[0] tag = parts[0]
orig_bits = line.replace(tag + " ", "")
# <0 candidates> etc
if "<" in orig_bits:
return tag, set(), orig_bits
# Ex: !30_06 !30_08 !30_11 30_07 # Ex: !30_06 !30_08 !30_11 30_07
bits = set(parts[1:]) bits = set(parts[1:])
return tag, bits return tag, bits, None
def zero_range(bits, wordmin, wordmax): def zero_range(bits, wordmin, wordmax):
@ -57,7 +62,7 @@ def bits_str(bits):
return ' '.join(sorted(list(bits))) return ' '.join(sorted(list(bits)))
def zero_groups(bits, zero_db, strict=True, verbose=False): def zero_groups(tag, bits, zero_db, strict=True, verbose=False):
""" """
See if a line occurs within a bit group See if a line occurs within a bit group
If it does, add 0 bits If it does, add 0 bits
@ -66,13 +71,21 @@ def zero_groups(bits, zero_db, strict=True, verbose=False):
Means find a line that has either of these bits Means find a line that has either of these bits
If either of them occurs, default bits in that set to zero If either of them occurs, default bits in that set to zero
Ex: 01_02 04_05 | 07_08 10_11 Ex: 01_02 04_05|07_08 10_11
If any bits from the first group occur, If any bits from the first group occur,
default bits in the second group to zero default bits in the second group to zero
Ex: 01_02 04_05,ALL_ZERO
ALL_ZERO is an enum that is part of the group but is all 0
It must have 0 candidates
strict: assert that the size of the given group is the size of the given mask strict: assert that the size of the given group is the size of the given mask
""" """
for zdb in zero_db: for zdb in zero_db:
allzero_tag = None
if "," in zdb:
zdb, allzero_tag = zdb.split(",")
if "|" in zdb: if "|" in zdb:
a, b = zdb.split("|") a, b = zdb.split("|")
a = a.split() a = a.split()
@ -81,39 +94,39 @@ def zero_groups(bits, zero_db, strict=True, verbose=False):
a = zdb.split() a = zdb.split()
b = a b = a
match = False bitmatch = False
for bit in a: for bit in a:
if bit in bits: if bit in bits:
match = True bitmatch = True
if match:
if not (bitmatch or allzero_tag == tag):
continue
bits_orig = set(bits) bits_orig = set(bits)
for bit in b: for bit in b:
if bit not in bits: if bit not in bits:
bits.add("!" + bit) bits.add("!" + bit)
verbose and print( verbose and print(
"Grouped: %s => %s" % (bits_str(bits_orig), bits_str(bits))) "Grouped %s: %s => %s" %
(tag, bits_str(bits_orig), bits_str(bits)))
if a == b and strict: if a == b and strict:
assert len(bits) == len( assert len(bits) == len(
a), "Mask size %u != DB entry size %u: %s" % ( a), "Mask size %u != DB entry size %u: %s" % (
len(a), len(bits), bits_str(bits)) len(a), len(bits), bits_str(bits))
def add_zero_bits(db_root, tile_type, zero_db, clb_int=False, verbose=False): def add_zero_bits(fn_in, fn_out, zero_db, clb_int=False, 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)
If an entry has any of the If an entry has any of the
''' '''
dbfile = "%s/segbits_%s.db" % (db_root, tile_type)
new_lines = set() new_lines = set()
changes = 0 changes = 0
verbose and print("zb %s: %s" % (dbfile, os.path.exists(dbfile)))
if not os.path.exists(dbfile):
return None
llast = None llast = None
with open(dbfile, "r") as f: with open(fn_in, "r") as f:
for line in f: for line in f:
# Hack: skip duplicate lines # Hack: skip duplicate lines
# This happens while merging a new multibit entry # This happens while merging a new multibit entry
@ -121,21 +134,19 @@ def add_zero_bits(db_root, tile_type, zero_db, clb_int=False, verbose=False):
if line == llast: if line == llast:
continue continue
tag, bits = parse_line(line) tag, bits, mode = parse_line(line)
assert mode not in (
"<const0>", "<const1>"), "Entries must be resolved"
if mode:
assert mode == "<0 candidates>"
""" """
This appears to be a large range of one hot interconnect bits This appears to be a large range of one hot interconnect bits
They are immediately before the first CLB real bits They are immediately before the first CLB real bits
""" """
# FIXME: handle these better
# https://github.com/SymbiFlow/prjxray/issues/232
orig_bits = line.replace(tag + " ", "")
if orig_bits in ("<const0>", "<0 candidates>"):
print("WARNING: dropping %s" % line)
changes += 1
continue
if clb_int: if clb_int:
zero_range(bits, 22, 25) zero_range(bits, 22, 25)
zero_groups(bits, zero_db, strict=not clb_int, verbose=verbose) zero_groups(
tag, bits, zero_db, strict=not clb_int, verbose=verbose)
new_line = " ".join([tag] + sorted(bits)) new_line = " ".join([tag] + sorted(bits))
if new_line != line: if new_line != line:
@ -143,7 +154,7 @@ def add_zero_bits(db_root, tile_type, zero_db, clb_int=False, verbose=False):
new_lines.add(new_line) new_lines.add(new_line)
llast = line llast = line
with open(dbfile, "w") as f: with open(fn_out, "w") as f:
for line in sorted(new_lines): for line in sorted(new_lines):
print(line, file=f) print(line, file=f)
@ -200,31 +211,16 @@ def load_zero_db(fn):
return ret return ret
def run( def update_seg_fns(fn_inouts, zero_db, clb_int, lazy=False, verbose=False):
db_root,
clb_int=False,
zero_db_fn=None,
zero_tile_types=None,
verbose=False):
if clb_int:
zero_db = clb_int_zero_db
# clblx is used by the CLB fuzzers before being expanded to DB
zero_tile_types = [
"int_l", "int_r", "clbll_l", "clbll_r", "clblm_l", "clblm_r",
"clblx"
]
else:
assert zero_db_fn
assert zero_tile_types
zero_db = load_zero_db(zero_db_fn)
print("CLB INT mode: %s" % clb_int)
print("Segbit groups: %s" % len(zero_db))
seg_files = 0 seg_files = 0
seg_lines = 0 seg_lines = 0
for tile_type in zero_tile_types: for fn_in, fn_out in fn_inouts:
verbose and print("zb %s: %s" % (fn_in, os.path.exists(fn_in)))
if lazy and not os.path.exists(fn_in):
continue
changes = add_zero_bits( changes = add_zero_bits(
db_root, tile_type, zero_db, clb_int=clb_int, verbose=verbose) fn_in, fn_out, zero_db, clb_int=clb_int, verbose=verbose)
if changes is not None: if changes is not None:
seg_files += 1 seg_files += 1
seg_lines += changes seg_lines += changes
@ -232,7 +228,8 @@ def run(
"Segbit: checked %u files w/ %u changed lines" % "Segbit: checked %u files w/ %u changed lines" %
(seg_files, seg_lines)) (seg_files, seg_lines))
if clb_int:
def update_masks(db_root):
for mask_db, src_dbs in [ for mask_db, src_dbs in [
("clbll_l", ("clbll_l", "int_l")), ("clbll_l", ("clbll_l", "int_l")),
("clbll_r", ("clbll_r", "int_r")), ("clbll_r", ("clbll_r", "int_r")),
@ -259,6 +256,54 @@ def run(
print("Mask: checked files") print("Mask: checked files")
def update_segs(
db_root, clb_int, seg_fn_in, seg_fn_out, zero_db_fn, verbose=False):
if clb_int:
zero_db = clb_int_zero_db
lazy = True
def gen_fns():
for tile_type in ["int_l", "int_r", "clbll_l", "clbll_r",
"clblm_l", "clblm_r"]:
fn = "%s/segbits_%s.db" % (db_root, tile_type)
yield (fn, fn)
fn_inouts = list(gen_fns())
else:
assert seg_fn_in
assert zero_db_fn
lazy = False
if not seg_fn_out:
seg_fn_out = seg_fn_in
fn_inouts = [(seg_fn_in, seg_fn_out)]
zero_db = load_zero_db(zero_db_fn)
print("CLB INT mode: %s" % clb_int)
print("Segbit groups: %s" % len(zero_db))
update_seg_fns(fn_inouts, zero_db, clb_int, lazy=lazy, verbose=verbose)
def run(
db_root,
clb_int=False,
zero_db_fn=None,
seg_fn_in=None,
seg_fn_out=None,
verbose=False):
# Probably should split this into two programs
update_segs(
db_root,
clb_int=clb_int,
seg_fn_in=seg_fn_in,
seg_fn_out=seg_fn_out,
zero_db_fn=zero_db_fn,
verbose=verbose)
if clb_int:
update_masks()
def main(): def main():
import argparse import argparse
@ -269,16 +314,13 @@ def main():
parser.add_argument( parser.add_argument(
'--clb-int', action='store_true', help='Fixup CLB interconnect') '--clb-int', action='store_true', help='Fixup CLB interconnect')
parser.add_argument('--zero-db', help='Apply custom patches') parser.add_argument('--zero-db', help='Apply custom patches')
parser.add_argument('--zero-tile-types', help='') parser.add_argument('--seg-fn-in', help='')
parser.add_argument('--seg-fn-out', help='')
args = parser.parse_args() args = parser.parse_args()
# XXX: can auto detect this?
zero_tile_types = args.zero_tile_types.split(
",") if args.zero_tile_types else None
run( run(
args.db_root, args.clb_int, args.zero_db, zero_tile_types, args.db_root, args.clb_int, args.zero_db, args.seg_fn_in,
args.verbose) args.seg_fn_out, args.verbose)
if __name__ == '__main__': if __name__ == '__main__':