prjxray/fuzzers/030-iob/check_results.py

130 lines
3.5 KiB
Python

""" Sanity checks FASM output from IOB fuzzer.
The IOB fuzzer is fairly complicated, and it's output is hard to verify by
inspected. For this reason, check_results.py was written to compare the
specimen's generated and their FASM output. The FASM output does pose a
chicken and egg issue. The test procedure is a follows:
1. Build the database (e.g. make -j<N> run)
2. Build the database again (e.g. make -j<N> run)
3. Run check_results.py
The second time that the database is run, the FASM files in the specimen's
will have the bits documented by fuzzer.
"""
import os
import os.path
from prjxray import verilog
import json
import generate
def process_parts(parts):
if parts[0] == 'INOUT':
yield 'type', 'IOBUF_INTERMDISABLE'
if parts[0] == 'IN_ONLY':
yield 'type', 'IBUF'
if parts[0] == 'SLEW':
yield 'SLEW', verilog.quote(parts[1])
if parts[0] == 'PULLTYPE':
yield 'PULLTYPE', verilog.quote(parts[1])
if len(parts) > 1 and parts[1] == 'IN':
yield 'IOSTANDARDS', parts[0].split('_')
if len(parts) > 1 and parts[1] == 'DRIVE':
yield 'IOSTANDARDS', parts[0].split('_')
yield 'DRIVES', parts[2].split('_')
def create_sites_from_fasm(root):
sites = {}
with open(os.path.join(root, 'design.fasm')) as f:
for l in f:
if 'IOB33' not in l:
continue
parts = l.strip().split('.')
tile = parts[0]
site = parts[1]
if (tile, site) not in sites:
sites[(tile, site)] = {
'tile': tile,
'site_key': site,
}
for key, value in process_parts(parts[2:]):
sites[(tile, site)][key] = value
for key in sites:
if 'type' not in sites[key]:
if 'IOSTANDARDS' not in sites[key]:
sites[key]['type'] = None
else:
assert 'IOSTANDARDS' in sites[key], sites[key]
assert 'DRIVES' in sites[key]
sites[key]['type'] = "OBUF"
return sites
def process_specimen(root):
sites = create_sites_from_fasm(root)
with open(os.path.join(root, 'params.jl')) as f:
params = json.load(f)
for p in params:
tile = p['tile']
site = p['site']
site_y = int(site[site.find('Y') + 1:]) % 2
if generate.skip_broken_tiles(p):
continue
site_key = 'IOB_Y{}'.format(site_y)
if (tile, site_key) not in sites:
assert p['type'] is None, p
continue
site_from_fasm = sites[(tile, site_key)]
assert p['type'] == site_from_fasm['type'], (
tile, site_key, p, site_from_fasm)
if p['type'] is None:
continue
assert p['PULLTYPE'] == site_from_fasm['PULLTYPE'], (
tile, site_key, p, site_from_fasm)
assert verilog.unquote(
p['IOSTANDARD']) in site_from_fasm['IOSTANDARDS'], (
tile, site_key, p, site_from_fasm)
if p['type'] != 'IBUF':
assert p['SLEW'] == site_from_fasm['SLEW'], (
tile, site_key, p, site_from_fasm)
assert 'I{}'.format(p['DRIVE']) in site_from_fasm['DRIVES'], (
tile, site_key, p, site_from_fasm)
def main():
for root, dirs, files in os.walk('build'):
if os.path.basename(root).startswith('specimen_'):
print('Processing', os.path.basename(root))
process_specimen(root)
print('No errors found!')
if __name__ == "__main__":
main()