From a7ba547acb9dba6a39b94ef8f58bb4edec540eef Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Tue, 23 Jul 2019 13:38:03 -0700 Subject: [PATCH] Filter out non-IOB bits. Also add output from LiteX to verify IOB FASM features. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fuzzers/030-iob/check_results.py | 139 +++++++++++++++++++---------- fuzzers/030-iob/generate.py | 2 +- fuzzers/030-iob/generate.tcl | 2 + minitests/litex/src.yosys/Makefile | 1 + minitests/litex/src.yosys/top.tcl | 34 +++++++ 5 files changed, 132 insertions(+), 46 deletions(-) diff --git a/fuzzers/030-iob/check_results.py b/fuzzers/030-iob/check_results.py index 93acb0aa..ea22c473 100644 --- a/fuzzers/030-iob/check_results.py +++ b/fuzzers/030-iob/check_results.py @@ -13,6 +13,7 @@ The second time that the database is run, the FASM files in the specimen's will have the bits documented by fuzzer. """ +import argparse import os import os.path from prjxray import verilog @@ -21,11 +22,8 @@ import generate def process_parts(parts): - if parts[0] == 'INOUT': - yield 'type', 'IOBUF_INTERMDISABLE' - if parts[-1] == 'IN_ONLY': - yield 'type', 'IBUF' + yield 'type', ['IBUF'] if len(parts) > 2 and parts[-2] == 'SLEW': yield 'SLEW', verilog.quote(parts[-1]) @@ -35,6 +33,7 @@ def process_parts(parts): if len(parts) > 1 and parts[1] == 'IN': yield 'IOSTANDARDS', parts[0].split('_') + yield 'IN', True if len(parts) > 1 and parts[1] == 'DRIVE': yield 'IOSTANDARDS', parts[0].split('_') @@ -45,10 +44,10 @@ def process_parts(parts): yield 'DRIVES', parts[2].split('_') -def create_sites_from_fasm(root): +def create_sites_from_fasm(fasm_file): sites = {} - with open(os.path.join(root, 'design.fasm')) as f: + with open(fasm_file) as f: for l in f: if 'IOB33' not in l: continue @@ -72,74 +71,124 @@ def create_sites_from_fasm(root): else: assert 'IOSTANDARDS' in sites[key], sites[key] assert 'DRIVES' in sites[key], sites[key] - sites[key]['type'] = "OBUF" + + if 'IN' in sites[key]: + sites[key]['type'] = ['IOBUF', 'IOBUF_INTERMDISABLE'] + else: + sites[key]['type'] = [ + "OBUF", + "OBUFDS_DUAL_BUF", + "OBUFTDS_DUAL_BUF", + ] return sites -def process_specimen(root): - sites = create_sites_from_fasm(root) +def process_specimen(fasm_file, params_json): + sites = create_sites_from_fasm(fasm_file) - with open(os.path.join(root, 'params.json')) as f: + with open(params_json) as f: params = json.load(f) for p in params['tiles']: tile = p['tile'] - site = p['site'] - site_y = int(site[site.find('Y') + 1:]) % 2 + for site in p['site'].split(' '): + site_y = int(site[site.find('Y') + 1:]) % 2 - if generate.skip_broken_tiles(p): - continue + if generate.skip_broken_tiles(p): + continue - site_key = 'IOB_Y{}'.format(site_y) + site_key = 'IOB_Y{}'.format(site_y) - if (tile, site_key) not in sites: - assert p['type'] is None, p - continue + if (tile, site_key) not in sites: + assert p['type'] is None, p + continue - site_from_fasm = sites[(tile, site_key)] + site_from_fasm = sites[(tile, site_key)] - assert p['type'] == site_from_fasm['type'], ( - tile, site_key, p['type'], site_from_fasm['type']) + assert p['type'] in site_from_fasm['type'], ( + tile, site_key, p['type'], site_from_fasm['type']) - if p['type'] is None: - continue + if p['type'] is None: + continue - assert p['PULLTYPE'] == site_from_fasm['PULLTYPE'], ( - tile, site_key, p, site_from_fasm) + assert 'PULLTYPE' in p, p + assert 'PULLTYPE' in site_from_fasm, site_from_fasm - assert 'IOSTANDARDS' in site_from_fasm, (root, tile, site) + if verilog.unquote(p['PULLTYPE']) == '': + # Default is None. + pulltype = verilog.quote('NONE') + else: + pulltype = p['PULLTYPE'] - assert verilog.unquote( - p['IOSTANDARD']) in site_from_fasm['IOSTANDARDS'], ( - p['IOSTANDARD'], - site_from_fasm['IOSTANDARDS'], - ) - - if p['type'] != 'IBUF': - assert p['SLEW'] == site_from_fasm['SLEW'], ( + assert pulltype == site_from_fasm['PULLTYPE'], ( tile, site_key, p, site_from_fasm) - assert 'DRIVES' not in p, p - assert 'DRIVES' in site_from_fasm, ( - tile, site, p['type'], site_from_fasm) + assert 'IOSTANDARDS' in site_from_fasm, (tile, site) - if p['DRIVE'] is None: - assert None in site_from_fasm['DRIVES'], ( - tile, site_key, p['DRIVE'], site_from_fasm['DRIVES']) - else: - assert 'I{}'.format(p['DRIVE']) in site_from_fasm['DRIVES'], ( - tile, site_key, p['DRIVE'], site_from_fasm['DRIVES']) + iostandard = verilog.unquote(p['IOSTANDARD']) + if iostandard.startswith('DIFF_'): + iostandard = iostandard[5:] + + assert iostandard in site_from_fasm['IOSTANDARDS'], ( + p['IOSTANDARD'], + site_from_fasm['IOSTANDARDS'], + ) + + if p['type'] != 'IBUF': + if verilog.unquote(p['SLEW']) == '': + # Default is None. + slew = verilog.quote('SLOW') + else: + slew = p['SLEW'] + + assert slew == site_from_fasm['SLEW'], ( + tile, site_key, p, site_from_fasm) + + assert 'DRIVES' not in p, p + assert 'DRIVES' in site_from_fasm, ( + tile, site, p['type'], site_from_fasm) + + if p['DRIVE'] is None: + assert None in site_from_fasm['DRIVES'], ( + tile, site_key, p['DRIVE'], site_from_fasm['DRIVES']) + elif p['DRIVE'] is '': + if None in site_from_fasm['DRIVES']: + # IOSTANDARD has not DRIVE setting, ignore + pass + else: + # Check that drive is at default + assert 'I12' in site_from_fasm['DRIVES'], ( + tile, site_key, p['DRIVE'], site_from_fasm['DRIVES']) + else: + assert 'I{}'.format(p['DRIVE']) in site_from_fasm['DRIVES'], ( + tile, site_key, p['DRIVE'], site_from_fasm['DRIVES']) -def main(): +def scan_specimens(): for root, dirs, files in os.walk('build'): if os.path.basename(root).startswith('specimen_'): print('Processing', os.path.basename(root)) - process_specimen(root) + process_specimen( + fasm_file=os.path.join(root, 'design.fasm'), + params_json=os.path.join(root, 'params.json')) print('No errors found!') +def main(): + parser = argparse.ArgumentParser(description="Verify IOB FASM vs BELs.") + + parser.add_argument('--fasm') + parser.add_argument('--params') + + args = parser.parse_args() + + if not args.fasm and not args.params: + scan_specimens() + else: + process_specimen(fasm_file=args.fasm, params_json=args.params) + + if __name__ == "__main__": main() diff --git a/fuzzers/030-iob/generate.py b/fuzzers/030-iob/generate.py index 97fb3a04..3989b4ee 100644 --- a/fuzzers/030-iob/generate.py +++ b/fuzzers/030-iob/generate.py @@ -8,7 +8,7 @@ import json def bitfilter(frame, word): - if frame < 26: + if frame < 38: return False return True diff --git a/fuzzers/030-iob/generate.tcl b/fuzzers/030-iob/generate.tcl index e0813c0e..f0776206 100644 --- a/fuzzers/030-iob/generate.tcl +++ b/fuzzers/030-iob/generate.tcl @@ -99,6 +99,8 @@ proc run {} { set_property CONFIG_VOLTAGE 3.3 [current_design] set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] set_property IS_ENABLED 0 [get_drc_checks {REQP-79}] + set_property IS_ENABLED 0 [get_drc_checks {REQP-144}] + set_property IS_ENABLED 0 [get_drc_checks {AVAL-74}] write_checkpoint -force design_pre_place.dcp diff --git a/minitests/litex/src.yosys/Makefile b/minitests/litex/src.yosys/Makefile index 334c21d9..027afe8c 100644 --- a/minitests/litex/src.yosys/Makefile +++ b/minitests/litex/src.yosys/Makefile @@ -25,6 +25,7 @@ top.edif: $(YOSYS) synth.ys $(SOURCES) top.bit: $(VIVADO) top.edif top.xdc top.tcl mkdir -p build cd build && $(XRAY_VIVADO) -mode batch -source ../top.tcl -nojournal -tempDir build -log vivado.log -verbose + python3 $(XRAY_DIR)/minitests/timing/clean_json5.py < build/iobuf_report.json5 > build/iobuf_report.json cp build/*.bit ./ top.fasm: top.bit diff --git a/minitests/litex/src.yosys/top.tcl b/minitests/litex/src.yosys/top.tcl index e4220653..3a1868a1 100644 --- a/minitests/litex/src.yosys/top.tcl +++ b/minitests/litex/src.yosys/top.tcl @@ -1,3 +1,33 @@ +proc write_iobuf_report {filename} { + set fp [open $filename w] + puts $fp "{ \"tiles\": \[" + foreach port [get_ports] { + set net [get_nets -of $port] + if { $net == "" } { + continue + } + + set cell [get_cells -of $net] + set site [get_sites -of $cell] + set tile [get_tiles -of $site] + + puts $fp "{" + puts $fp "\"port\": \"$port\"," + puts $fp "\"pad_wire\": \"$net\"," + puts $fp "\"cell\": \"$cell\"," + puts $fp "\"site\": \"$site\"," + puts $fp "\"tile\": \"$tile\"," + puts $fp "\"type\": \"[get_property REF_NAME $cell]\"," + puts $fp "\"IOSTANDARD\": \"\\\"[get_property IOSTANDARD $cell]\\\"\"," + puts $fp "\"PULLTYPE\": \"\\\"[get_property PULLTYPE $cell]\\\"\"," + puts $fp "\"DRIVE\": \"[get_property DRIVE $cell]\"," + puts $fp "\"SLEW\": \"\\\"[get_property SLEW $cell]\\\"\"," + puts $fp "}," + } + puts $fp "\]}" + close $fp +} + create_project -force -name top -part xc7a35ticsg324-1L read_xdc ../top.xdc read_edif ../top.edif @@ -23,4 +53,8 @@ report_power -file top_power.rpt set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] write_bitstream -force top.bit write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit "up 0x0 top.bit" -file top.bin + +write_iobuf_report iobuf_report.json5 + + quit