mirror of https://github.com/openXC7/prjxray.git
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>
This commit is contained in:
parent
aa331131f2
commit
a7ba547acb
|
|
@ -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.
|
will have the bits documented by fuzzer.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import argparse
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
from prjxray import verilog
|
from prjxray import verilog
|
||||||
|
|
@ -21,11 +22,8 @@ import generate
|
||||||
|
|
||||||
|
|
||||||
def process_parts(parts):
|
def process_parts(parts):
|
||||||
if parts[0] == 'INOUT':
|
|
||||||
yield 'type', 'IOBUF_INTERMDISABLE'
|
|
||||||
|
|
||||||
if parts[-1] == 'IN_ONLY':
|
if parts[-1] == 'IN_ONLY':
|
||||||
yield 'type', 'IBUF'
|
yield 'type', ['IBUF']
|
||||||
|
|
||||||
if len(parts) > 2 and parts[-2] == 'SLEW':
|
if len(parts) > 2 and parts[-2] == 'SLEW':
|
||||||
yield 'SLEW', verilog.quote(parts[-1])
|
yield 'SLEW', verilog.quote(parts[-1])
|
||||||
|
|
@ -35,6 +33,7 @@ def process_parts(parts):
|
||||||
|
|
||||||
if len(parts) > 1 and parts[1] == 'IN':
|
if len(parts) > 1 and parts[1] == 'IN':
|
||||||
yield 'IOSTANDARDS', parts[0].split('_')
|
yield 'IOSTANDARDS', parts[0].split('_')
|
||||||
|
yield 'IN', True
|
||||||
|
|
||||||
if len(parts) > 1 and parts[1] == 'DRIVE':
|
if len(parts) > 1 and parts[1] == 'DRIVE':
|
||||||
yield 'IOSTANDARDS', parts[0].split('_')
|
yield 'IOSTANDARDS', parts[0].split('_')
|
||||||
|
|
@ -45,10 +44,10 @@ def process_parts(parts):
|
||||||
yield 'DRIVES', parts[2].split('_')
|
yield 'DRIVES', parts[2].split('_')
|
||||||
|
|
||||||
|
|
||||||
def create_sites_from_fasm(root):
|
def create_sites_from_fasm(fasm_file):
|
||||||
sites = {}
|
sites = {}
|
||||||
|
|
||||||
with open(os.path.join(root, 'design.fasm')) as f:
|
with open(fasm_file) as f:
|
||||||
for l in f:
|
for l in f:
|
||||||
if 'IOB33' not in l:
|
if 'IOB33' not in l:
|
||||||
continue
|
continue
|
||||||
|
|
@ -72,74 +71,124 @@ def create_sites_from_fasm(root):
|
||||||
else:
|
else:
|
||||||
assert 'IOSTANDARDS' in sites[key], sites[key]
|
assert 'IOSTANDARDS' in sites[key], sites[key]
|
||||||
assert 'DRIVES' 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
|
return sites
|
||||||
|
|
||||||
|
|
||||||
def process_specimen(root):
|
def process_specimen(fasm_file, params_json):
|
||||||
sites = create_sites_from_fasm(root)
|
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)
|
params = json.load(f)
|
||||||
|
|
||||||
for p in params['tiles']:
|
for p in params['tiles']:
|
||||||
tile = p['tile']
|
tile = p['tile']
|
||||||
site = p['site']
|
for site in p['site'].split(' '):
|
||||||
site_y = int(site[site.find('Y') + 1:]) % 2
|
site_y = int(site[site.find('Y') + 1:]) % 2
|
||||||
|
|
||||||
if generate.skip_broken_tiles(p):
|
if generate.skip_broken_tiles(p):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
site_key = 'IOB_Y{}'.format(site_y)
|
site_key = 'IOB_Y{}'.format(site_y)
|
||||||
|
|
||||||
if (tile, site_key) not in sites:
|
if (tile, site_key) not in sites:
|
||||||
assert p['type'] is None, p
|
assert p['type'] is None, p
|
||||||
continue
|
continue
|
||||||
|
|
||||||
site_from_fasm = sites[(tile, site_key)]
|
site_from_fasm = sites[(tile, site_key)]
|
||||||
|
|
||||||
assert p['type'] == site_from_fasm['type'], (
|
assert p['type'] in site_from_fasm['type'], (
|
||||||
tile, site_key, p['type'], site_from_fasm['type'])
|
tile, site_key, p['type'], site_from_fasm['type'])
|
||||||
|
|
||||||
if p['type'] is None:
|
if p['type'] is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
assert p['PULLTYPE'] == site_from_fasm['PULLTYPE'], (
|
assert 'PULLTYPE' in p, p
|
||||||
tile, site_key, p, site_from_fasm)
|
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(
|
assert pulltype == site_from_fasm['PULLTYPE'], (
|
||||||
p['IOSTANDARD']) in site_from_fasm['IOSTANDARDS'], (
|
|
||||||
p['IOSTANDARD'],
|
|
||||||
site_from_fasm['IOSTANDARDS'],
|
|
||||||
)
|
|
||||||
|
|
||||||
if p['type'] != 'IBUF':
|
|
||||||
assert p['SLEW'] == site_from_fasm['SLEW'], (
|
|
||||||
tile, site_key, p, site_from_fasm)
|
tile, site_key, p, site_from_fasm)
|
||||||
|
|
||||||
assert 'DRIVES' not in p, p
|
assert 'IOSTANDARDS' in site_from_fasm, (tile, site)
|
||||||
assert 'DRIVES' in site_from_fasm, (
|
|
||||||
tile, site, p['type'], site_from_fasm)
|
|
||||||
|
|
||||||
if p['DRIVE'] is None:
|
iostandard = verilog.unquote(p['IOSTANDARD'])
|
||||||
assert None in site_from_fasm['DRIVES'], (
|
if iostandard.startswith('DIFF_'):
|
||||||
tile, site_key, p['DRIVE'], site_from_fasm['DRIVES'])
|
iostandard = iostandard[5:]
|
||||||
else:
|
|
||||||
assert 'I{}'.format(p['DRIVE']) in site_from_fasm['DRIVES'], (
|
assert iostandard in site_from_fasm['IOSTANDARDS'], (
|
||||||
tile, site_key, p['DRIVE'], site_from_fasm['DRIVES'])
|
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'):
|
for root, dirs, files in os.walk('build'):
|
||||||
if os.path.basename(root).startswith('specimen_'):
|
if os.path.basename(root).startswith('specimen_'):
|
||||||
print('Processing', os.path.basename(root))
|
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!')
|
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__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import json
|
||||||
|
|
||||||
|
|
||||||
def bitfilter(frame, word):
|
def bitfilter(frame, word):
|
||||||
if frame < 26:
|
if frame < 38:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,8 @@ proc run {} {
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [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-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
|
write_checkpoint -force design_pre_place.dcp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ top.edif: $(YOSYS) synth.ys $(SOURCES)
|
||||||
top.bit: $(VIVADO) top.edif top.xdc top.tcl
|
top.bit: $(VIVADO) top.edif top.xdc top.tcl
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build && $(XRAY_VIVADO) -mode batch -source ../top.tcl -nojournal -tempDir build -log vivado.log -verbose
|
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 ./
|
cp build/*.bit ./
|
||||||
|
|
||||||
top.fasm: top.bit
|
top.fasm: top.bit
|
||||||
|
|
|
||||||
|
|
@ -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
|
create_project -force -name top -part xc7a35ticsg324-1L
|
||||||
read_xdc ../top.xdc
|
read_xdc ../top.xdc
|
||||||
read_edif ../top.edif
|
read_edif ../top.edif
|
||||||
|
|
@ -23,4 +53,8 @@ report_power -file top_power.rpt
|
||||||
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
|
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
|
||||||
write_bitstream -force top.bit
|
write_bitstream -force top.bit
|
||||||
write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit "up 0x0 top.bit" -file top.bin
|
write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit "up 0x0 top.bit" -file top.bin
|
||||||
|
|
||||||
|
write_iobuf_report iobuf_report.json5
|
||||||
|
|
||||||
|
|
||||||
quit
|
quit
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue