Merge pull request #631 from antmicro/check-out-of-bound-bits

checkdb: optimized script and added out-of-bound check
This commit is contained in:
litghost 2019-02-12 09:56:25 -08:00 committed by GitHub
commit 8222b4089b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 60 deletions

View File

@ -172,45 +172,6 @@ def addr2btype(base_addr):
return block_type_i2s[block_type_i]
def gen_tile_bits(db_root, tilej, strict=False, verbose=False):
'''
For given tile yield
(absolute address, absolute FDRI bit offset, tag)
For each address space
Find applicable files
For each tag bit in those files, calculate absolute address and bit offsets
Sample file names:
segbits_clbll_l.db
segbits_int_l.db
segbits_bram_l.block_ram.db
'''
for block_type, blockj in tilej["bits"].items():
baseaddr = int(blockj["baseaddr"], 0)
bitbase = 32 * blockj["offset"]
if block_type == "CLB_IO_CLK":
fn = "%s/segbits_%s.db" % (db_root, tilej["type"].lower())
else:
fn = "%s/segbits_%s.db.%s" % (
db_root, tilej["type"].lower(), block_type.lower())
# tilegrid runs a lot earlier than fuzzers
# may not have been created yet
verbose and print("Check %s: %s" % (fn, os.path.exists(fn)))
if strict:
assert os.path.exists(fn)
elif not os.path.exists(fn):
continue
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():
# ex: build/specimen_001
specdir = os.getenv("SPECDIR")

View File

@ -17,7 +17,34 @@ import parsedb
import glob
def make_tile_mask(db_root, tile_name, tilej, strict=False, verbose=False):
def gen_tile_bits(tile_segbits, tile_bits):
'''
For given tile and corresponding db_file structure yield
(absolute address, absolute FDRI bit offset, tag)
For each tag bit in the corresponding block_type entry, calculate absolute address and bit offsets
'''
for block_type in tile_segbits:
assert block_type in tile_bits, "block type %s is not present in current tile" % block_type
block = tile_bits[block_type]
baseaddr = block.base_address
bitbase = 32 * block.offset
frames = block.frames
for tag in tile_segbits[block_type]:
for bit in tile_segbits[block_type][tag]:
# 31_06
word_column = bit.word_column
word_bit = bit.word_bit
assert word_column <= frames, "ERROR: bit out of bound --> tag: %s; word_column = %s; frames = %s" % (
tag, word_column, frames)
yield word_column + baseaddr, word_bit + bitbase, tag
def make_tile_mask(tile_segbits, tile_name, tile_bits):
'''
Return dict
key: (address, bit index)
@ -29,8 +56,7 @@ def make_tile_mask(db_root, tile_name, tilej, strict=False, verbose=False):
# We may want this to build them anyway
ret = dict()
for absaddr, bitaddr, tag in util.gen_tile_bits(
db_root, tilej, strict=strict, verbose=verbose):
for absaddr, bitaddr, tag in gen_tile_bits(tile_segbits, tile_bits):
name = "%s.%s" % (tile_name, tag)
ret.setdefault((absaddr, bitaddr), name)
return ret
@ -54,7 +80,7 @@ def parsedb_all(db_root, verbose=False):
print("mask_*.db: %d okay" % files)
def check_tile_overlap(db, db_root, strict=False, verbose=False):
def check_tile_overlap(db, verbose=False):
'''
Verifies that no two tiles use the same bit
@ -64,40 +90,59 @@ def check_tile_overlap(db, db_root, strict=False, verbose=False):
Throw an exception if two tiles share an address
'''
mall = dict()
tiles_type_done = dict()
tile_segbits = dict()
grid = db.grid()
tiles_checked = 0
def subtiles(tile_names):
for tile_name in tile_names:
yield tile_name, db.tilegrid[tile_name]
for tile_name in grid.tiles():
tile_info = grid.gridinfo_at_tilename(tile_name)
tile_type = tile_info.tile_type
tile_bits = tile_info.bits
for tile_name, tilej in db.tilegrid.items():
# for tile_name, tilej in subtiles(["CLBLL_L_X14Y112", "INT_L_X14Y112"]):
if tile_type not in tiles_type_done:
segbits = db.get_tile_segbits(tile_type).segbits
tile_segbits[tile_type] = segbits
mtile = make_tile_mask(
db_root, tile_name, tilej, strict=strict, verbose=verbose)
# If segbits has zero length the tile_type is marked True in order to be skipped
if len(segbits) == 0:
tiles_type_done[tile_type] = True
else:
tiles_type_done[tile_type] = False
mall[tile_type] = {}
if tiles_type_done[tile_type]:
continue
mtile = make_tile_mask(tile_segbits[tile_type], tile_name, tile_bits)
verbose and print(
"Checking %s, type %s, bits: %s" %
(tile_name, tilej["type"], len(mtile)))
(tile_name, tile_type, len(mtile)))
if len(mtile) == 0:
continue
collisions = set(mall.keys()).intersection(set(mtile.keys()))
collisions = set()
for bits in mtile.keys():
if bits in mall[tile_type].keys():
collisions.add(bits)
if collisions:
print("ERROR: %s collisions" % len(collisions))
for ck in sorted(collisions):
addr, bitaddr = ck
word, bit = util.addr_bit2word(bitaddr)
print(
" %s: had %s, got %s" %
(util.addr2str(addr, word, bit), mall[ck], mtile[ck]))
" %s: had %s, got %s" % (
util.addr2str(addr, word, bit), mall[tile_type][ck],
mtile[ck]))
raise ValueError("%s collisions" % len(collisions))
mall.update(mtile)
mall[tile_type].update(mtile)
tiles_checked += 1
print("Checked %s tiles, %s bits" % (tiles_checked, len(mall)))
def run(db_root, strict=False, verbose=False):
def run(db_root, verbose=False):
# Start by running a basic check on db files
print("Checking individual .db...")
parsedb_all(db_root, verbose=verbose)
@ -115,7 +160,7 @@ def run(db_root, strict=False, verbose=False):
verbose and print("")
print("Checking aggregate dir...")
check_tile_overlap(db, db_root, strict=strict, verbose=verbose)
check_tile_overlap(db, verbose=verbose)
def main():
@ -125,11 +170,10 @@ def main():
description="Parse a db repository, checking for consistency")
util.db_root_arg(parser)
parser.add_argument('--strict', action='store_true', help='')
parser.add_argument('--verbose', action='store_true', help='')
args = parser.parse_args()
run(args.db_root, strict=args.strict, verbose=args.verbose)
run(args.db_root, verbose=args.verbose)
if __name__ == '__main__':