mirror of https://github.com/openXC7/prjxray.git
Refactor IOB fuzzer.
- Add SSTL135 - Refactor process_rdb to handle varying SLEW by IOSTANDARD. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
ae526981a2
commit
aa331131f2
|
|
@ -1,10 +1,15 @@
|
||||||
N := 50
|
N := 50
|
||||||
|
SPECIMENS_DEPS := build/iobanks.txt
|
||||||
include ../fuzzer.mk
|
include ../fuzzer.mk
|
||||||
|
|
||||||
database: build/segbits_xiob33.db
|
database: build/segbits_xiob33.db
|
||||||
|
|
||||||
|
build/iobanks.txt: write_io_banks.tcl
|
||||||
|
mkdir -p build
|
||||||
|
cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/write_io_banks.tcl
|
||||||
|
|
||||||
build/segbits_xiob33.rdb: $(SPECIMENS_OK)
|
build/segbits_xiob33.rdb: $(SPECIMENS_OK)
|
||||||
${XRAY_SEGMATCH} -c 7 -o build/segbits_xiob33.rdb $$(find -name segdata_liob33.txt) $$(find -name segdata_riob33.txt)
|
${XRAY_SEGMATCH} -c 12 -o build/segbits_xiob33.rdb $$(find -name segdata_liob33.txt) $$(find -name segdata_riob33.txt)
|
||||||
|
|
||||||
build/segbits_xiob33.db: build/segbits_xiob33.rdb process_rdb.py bits.dbf
|
build/segbits_xiob33.db: build/segbits_xiob33.rdb process_rdb.py bits.dbf
|
||||||
python3 process_rdb.py build/segbits_xiob33.rdb > build/segbits_xiob33_processed.rdb
|
python3 process_rdb.py build/segbits_xiob33.rdb > build/segbits_xiob33_processed.rdb
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
38_92 39_93 38_94,IOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
38_92 39_93 38_94,IOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
||||||
38_106 38_110 39_105 39_109,IOB33.IOB_Y0.SLEW.FAST
|
38_106 39_107 39_111 38_106 38_110 39_105 39_109,IOB33.IOB_Y0.SLEW.FAST
|
||||||
39_33 38_34 39_35,IOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
39_33 38_34 39_35,IOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
||||||
38_18 38_22 39_17 39_21,IOB33.IOB_Y1.SLEW.FAST
|
39_21 38_16 38_20 38_18 38_22 39_17,IOB33.IOB_Y1.SLEW.FAST
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,11 @@ def process_parts(parts):
|
||||||
if parts[0] == 'INOUT':
|
if parts[0] == 'INOUT':
|
||||||
yield 'type', 'IOBUF_INTERMDISABLE'
|
yield 'type', 'IOBUF_INTERMDISABLE'
|
||||||
|
|
||||||
if parts[0] == 'IN_ONLY':
|
if parts[-1] == 'IN_ONLY':
|
||||||
yield 'type', 'IBUF'
|
yield 'type', 'IBUF'
|
||||||
|
|
||||||
if parts[0] == 'SLEW':
|
if len(parts) > 2 and parts[-2] == 'SLEW':
|
||||||
yield 'SLEW', verilog.quote(parts[1])
|
yield 'SLEW', verilog.quote(parts[-1])
|
||||||
|
|
||||||
if parts[0] == 'PULLTYPE':
|
if parts[0] == 'PULLTYPE':
|
||||||
yield 'PULLTYPE', verilog.quote(parts[1])
|
yield 'PULLTYPE', verilog.quote(parts[1])
|
||||||
|
|
@ -38,6 +38,10 @@ def process_parts(parts):
|
||||||
|
|
||||||
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('_')
|
||||||
|
|
||||||
|
if parts[2] == 'I_FIXED':
|
||||||
|
yield 'DRIVES', [None]
|
||||||
|
else:
|
||||||
yield 'DRIVES', parts[2].split('_')
|
yield 'DRIVES', parts[2].split('_')
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -67,7 +71,7 @@ def create_sites_from_fasm(root):
|
||||||
sites[key]['type'] = None
|
sites[key]['type'] = None
|
||||||
else:
|
else:
|
||||||
assert 'IOSTANDARDS' in sites[key], sites[key]
|
assert 'IOSTANDARDS' in sites[key], sites[key]
|
||||||
assert 'DRIVES' in sites[key]
|
assert 'DRIVES' in sites[key], sites[key]
|
||||||
sites[key]['type'] = "OBUF"
|
sites[key]['type'] = "OBUF"
|
||||||
|
|
||||||
return sites
|
return sites
|
||||||
|
|
@ -76,10 +80,10 @@ def create_sites_from_fasm(root):
|
||||||
def process_specimen(root):
|
def process_specimen(root):
|
||||||
sites = create_sites_from_fasm(root)
|
sites = create_sites_from_fasm(root)
|
||||||
|
|
||||||
with open(os.path.join(root, 'params.jl')) as f:
|
with open(os.path.join(root, 'params.json')) as f:
|
||||||
params = json.load(f)
|
params = json.load(f)
|
||||||
|
|
||||||
for p in params:
|
for p in params['tiles']:
|
||||||
tile = p['tile']
|
tile = p['tile']
|
||||||
site = p['site']
|
site = p['site']
|
||||||
site_y = int(site[site.find('Y') + 1:]) % 2
|
site_y = int(site[site.find('Y') + 1:]) % 2
|
||||||
|
|
@ -96,7 +100,7 @@ def process_specimen(root):
|
||||||
site_from_fasm = sites[(tile, site_key)]
|
site_from_fasm = sites[(tile, site_key)]
|
||||||
|
|
||||||
assert p['type'] == site_from_fasm['type'], (
|
assert p['type'] == site_from_fasm['type'], (
|
||||||
tile, site_key, p, site_from_fasm)
|
tile, site_key, p['type'], site_from_fasm['type'])
|
||||||
|
|
||||||
if p['type'] is None:
|
if p['type'] is None:
|
||||||
continue
|
continue
|
||||||
|
|
@ -104,16 +108,28 @@ def process_specimen(root):
|
||||||
assert p['PULLTYPE'] == site_from_fasm['PULLTYPE'], (
|
assert p['PULLTYPE'] == site_from_fasm['PULLTYPE'], (
|
||||||
tile, site_key, p, site_from_fasm)
|
tile, site_key, p, site_from_fasm)
|
||||||
|
|
||||||
|
assert 'IOSTANDARDS' in site_from_fasm, (root, tile, site)
|
||||||
|
|
||||||
assert verilog.unquote(
|
assert verilog.unquote(
|
||||||
p['IOSTANDARD']) in site_from_fasm['IOSTANDARDS'], (
|
p['IOSTANDARD']) in site_from_fasm['IOSTANDARDS'], (
|
||||||
tile, site_key, p, site_from_fasm)
|
p['IOSTANDARD'],
|
||||||
|
site_from_fasm['IOSTANDARDS'],
|
||||||
|
)
|
||||||
|
|
||||||
if p['type'] != 'IBUF':
|
if p['type'] != 'IBUF':
|
||||||
assert p['SLEW'] == site_from_fasm['SLEW'], (
|
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 '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'])
|
||||||
|
else:
|
||||||
assert 'I{}'.format(p['DRIVE']) in site_from_fasm['DRIVES'], (
|
assert 'I{}'.format(p['DRIVE']) in site_from_fasm['DRIVES'], (
|
||||||
tile, site_key, p, site_from_fasm)
|
tile, site_key, p['DRIVE'], site_from_fasm['DRIVES'])
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ def bitfilter(frame, word):
|
||||||
|
|
||||||
|
|
||||||
def mk_drive_opt(iostandard, drive):
|
def mk_drive_opt(iostandard, drive):
|
||||||
|
if drive is None:
|
||||||
|
drive = '_FIXED'
|
||||||
return '{}.DRIVE.I{}'.format(iostandard, drive)
|
return '{}.DRIVE.I{}'.format(iostandard, drive)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -37,13 +39,15 @@ def drives_for_iostandard(iostandard):
|
||||||
drives = [4, 8, 12, 16, 24]
|
drives = [4, 8, 12, 16, 24]
|
||||||
elif iostandard == 'LVCMOS12':
|
elif iostandard == 'LVCMOS12':
|
||||||
drives = [4, 8, 12]
|
drives = [4, 8, 12]
|
||||||
|
elif iostandard == 'SSTL135':
|
||||||
|
return ['_FIXED']
|
||||||
else:
|
else:
|
||||||
drives = [4, 8, 12, 16]
|
drives = [4, 8, 12, 16]
|
||||||
|
|
||||||
return drives
|
return drives
|
||||||
|
|
||||||
|
|
||||||
STEPDOWN_IOSTANDARDS = ['LVCMOS12', 'LVCMOS15', 'LVCMOS18']
|
STEPDOWN_IOSTANDARDS = ['LVCMOS12', 'LVCMOS15', 'LVCMOS18', 'SSTL135']
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -54,10 +58,10 @@ def main():
|
||||||
di[0],IOB_X0Y107,LIOB33_X0Y107,A21,PULLDOWN
|
di[0],IOB_X0Y107,LIOB33_X0Y107,A21,PULLDOWN
|
||||||
di[10],IOB_X0Y147,LIOB33_X0Y147,F14,PULLUP
|
di[10],IOB_X0Y147,LIOB33_X0Y147,F14,PULLUP
|
||||||
'''
|
'''
|
||||||
with open('params.jl', 'r') as f:
|
with open('params.json', 'r') as f:
|
||||||
design = json.load(f)
|
design = json.load(f)
|
||||||
|
|
||||||
for d in design:
|
for d in design['tiles']:
|
||||||
site = d['site']
|
site = d['site']
|
||||||
|
|
||||||
if skip_broken_tiles(d):
|
if skip_broken_tiles(d):
|
||||||
|
|
@ -65,44 +69,31 @@ def main():
|
||||||
|
|
||||||
iostandard = verilog.unquote(d['IOSTANDARD'])
|
iostandard = verilog.unquote(d['IOSTANDARD'])
|
||||||
|
|
||||||
stepdown = iostandard in STEPDOWN_IOSTANDARDS
|
segmk.add_site_tag(
|
||||||
segmk.add_site_tag(site, '_'.join(STEPDOWN_IOSTANDARDS), stepdown)
|
site, '_'.join(STEPDOWN_IOSTANDARDS) + '.STEPDOWN',
|
||||||
|
iostandard in STEPDOWN_IOSTANDARDS)
|
||||||
|
|
||||||
if d['type'] is None:
|
if d['type'] is None:
|
||||||
segmk.add_site_tag(site, 'INOUT', 0)
|
segmk.add_site_tag(site, 'INOUT', 0)
|
||||||
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 0)
|
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 0)
|
||||||
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
|
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
|
||||||
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 0)
|
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 0)
|
||||||
for drive in drives_for_iostandard(iostandard):
|
segmk.add_site_tag(site, '{}.IN_ONLY'.format(iostandard), 0)
|
||||||
segmk.add_site_tag(
|
|
||||||
site, '{}.DRIVE.I{}.IN_OUT_COMMON'.format(
|
|
||||||
iostandard, drive), 0)
|
|
||||||
elif d['type'] == 'IBUF':
|
elif d['type'] == 'IBUF':
|
||||||
segmk.add_site_tag(site, 'INOUT', 0)
|
segmk.add_site_tag(site, 'INOUT', 0)
|
||||||
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
||||||
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 1)
|
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 1)
|
||||||
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 0)
|
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 0)
|
||||||
for drive in drives_for_iostandard(iostandard):
|
segmk.add_site_tag(site, '{}.IN_ONLY'.format(iostandard), 1)
|
||||||
segmk.add_site_tag(
|
|
||||||
site, '{}.DRIVE.I{}.IN_OUT_COMMON'.format(
|
|
||||||
iostandard, drive), 1)
|
|
||||||
elif d['type'] == 'OBUF':
|
elif d['type'] == 'OBUF':
|
||||||
segmk.add_site_tag(site, 'INOUT', 0)
|
segmk.add_site_tag(site, 'INOUT', 0)
|
||||||
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
||||||
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
|
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
|
||||||
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
|
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
|
||||||
for drive in drives_for_iostandard(iostandard):
|
|
||||||
if drive == d['DRIVE']:
|
|
||||||
segmk.add_site_tag(
|
|
||||||
site, '{}.DRIVE.I{}.IN_OUT_COMMON'.format(
|
|
||||||
iostandard, drive), 1)
|
|
||||||
else:
|
|
||||||
segmk.add_site_tag(
|
|
||||||
site, '{}.DRIVE.I{}.IN_OUT_COMMON'.format(
|
|
||||||
iostandard, drive), 0)
|
|
||||||
elif d['type'] == 'IOBUF_INTERMDISABLE':
|
elif d['type'] == 'IOBUF_INTERMDISABLE':
|
||||||
segmk.add_site_tag(site, 'INOUT', 1)
|
segmk.add_site_tag(site, 'INOUT', 1)
|
||||||
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
||||||
|
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 1)
|
||||||
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
|
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
|
||||||
|
|
||||||
if d['type'] is not None:
|
if d['type'] is not None:
|
||||||
|
|
@ -126,13 +117,16 @@ def main():
|
||||||
|
|
||||||
drive_opts.add(mk_drive_opt(opt, drive_opt))
|
drive_opts.add(mk_drive_opt(opt, drive_opt))
|
||||||
|
|
||||||
|
drive_opts.add(mk_drive_opt("SSTL135", None))
|
||||||
|
|
||||||
segmaker.add_site_group_zero(
|
segmaker.add_site_group_zero(
|
||||||
segmk, site, '', drive_opts, mk_drive_opt('LVCMOS25', '12'),
|
segmk, site, '', drive_opts, mk_drive_opt('LVCMOS25', '12'),
|
||||||
mk_drive_opt(iostandard, d['DRIVE']))
|
mk_drive_opt(iostandard, d['DRIVE']))
|
||||||
|
|
||||||
segmaker.add_site_group_zero(
|
for opt in ["SLOW", "FAST"]:
|
||||||
segmk, site, "SLEW.", ("SLOW", "FAST"), "FAST",
|
segmk.add_site_tag(
|
||||||
verilog.unquote(d['SLEW']))
|
site, iostandard + ".SLEW." + opt, opt == verilog.unquote(
|
||||||
|
d['SLEW']))
|
||||||
|
|
||||||
if 'ibufdisable_wire' in d:
|
if 'ibufdisable_wire' in d:
|
||||||
segmk.add_site_tag(
|
segmk.add_site_tag(
|
||||||
|
|
|
||||||
|
|
@ -75,12 +75,25 @@ proc loc_pins {} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc set_vref {} {
|
||||||
|
set fp [open "iobank_vref.csv" r]
|
||||||
|
for {gets $fp line} {$line != ""} {gets $fp line} {
|
||||||
|
set parts [split $line ","]
|
||||||
|
set iobank [lindex $parts 0]
|
||||||
|
set vref [lindex $parts 1]
|
||||||
|
puts "setting $iobank ([get_iobanks $iobank]) to INTERNAL_VREF $vref"
|
||||||
|
set_property INTERNAL_VREF $vref [get_iobanks $iobank]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proc run {} {
|
proc run {} {
|
||||||
create_project -force -part $::env(XRAY_PART) design design
|
create_project -force -part $::env(XRAY_PART) design design
|
||||||
read_verilog top.v
|
read_verilog top.v
|
||||||
synth_design -top top
|
synth_design -top top
|
||||||
|
|
||||||
loc_pins
|
loc_pins
|
||||||
|
set_vref
|
||||||
|
|
||||||
|
|
||||||
set_property CFGBVS VCCO [current_design]
|
set_property CFGBVS VCCO [current_design]
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||||
|
|
|
||||||
|
|
@ -66,127 +66,129 @@ def main():
|
||||||
iostandard_lines = []
|
iostandard_lines = []
|
||||||
with open(args.input_rdb) as f:
|
with open(args.input_rdb) as f:
|
||||||
for l in f:
|
for l in f:
|
||||||
if ('.LVCMOS' in l or '.LVTTL' in l) and 'IOB_' in l:
|
if ('.SSTL135' in l or '.LVCMOS' in l
|
||||||
|
or '.LVTTL' in l) and 'IOB_' in l:
|
||||||
iostandard_lines.append(l)
|
iostandard_lines.append(l)
|
||||||
else:
|
else:
|
||||||
print(l.strip())
|
print(l.strip())
|
||||||
|
|
||||||
common_in_only_bits = {
|
sites = {}
|
||||||
'IOB_Y0': set(),
|
|
||||||
'IOB_Y1': set(),
|
|
||||||
}
|
|
||||||
for l in iostandard_lines:
|
|
||||||
if 'IN_OUT_COMMON' in l:
|
|
||||||
common_in_only_bits[get_site(l)] |= parse_bits(l)
|
|
||||||
|
|
||||||
for site in sorted(common_in_only_bits):
|
|
||||||
print(
|
|
||||||
'IOB33.{}.IN_ONLY'.format(site), ' '.join(
|
|
||||||
common_in_only_bits[site]))
|
|
||||||
|
|
||||||
iostandard_in = {}
|
|
||||||
outs = {}
|
|
||||||
drives = {}
|
|
||||||
in_use = {}
|
|
||||||
|
|
||||||
for l in iostandard_lines:
|
for l in iostandard_lines:
|
||||||
name = get_name(l)
|
feature = get_name(l)
|
||||||
|
feature_parts = feature.split('.')
|
||||||
site = get_site(l)
|
site = get_site(l)
|
||||||
iostandard = name.split('.')[2]
|
iostandard = feature_parts[2]
|
||||||
|
|
||||||
if name.endswith('.IN_USE'):
|
bits = parse_bits(l)
|
||||||
in_use[(site, iostandard)] = parse_bits(l)
|
bits = filter_bits(site, bits)
|
||||||
|
|
||||||
for l in iostandard_lines:
|
if site not in sites:
|
||||||
name = get_name(l)
|
sites[site] = {}
|
||||||
site = get_site(l)
|
|
||||||
iostandard = name.split('.')[2]
|
|
||||||
|
|
||||||
if name.endswith('.IN'):
|
group = feature_parts[3]
|
||||||
in_bits = parse_bits(l) | in_use[(site, iostandard)]
|
if group not in sites[site]:
|
||||||
|
sites[site][group] = {}
|
||||||
|
|
||||||
if in_bits not in iostandard_in:
|
if group in ['DRIVE', 'SLEW']:
|
||||||
iostandard_in[in_bits] = []
|
enum = feature_parts[4]
|
||||||
|
sites[site][group][(iostandard, enum)] = bits
|
||||||
|
elif group in ['IN', 'IN_ONLY', 'IN_USE', 'OUT', 'STEPDOWN']:
|
||||||
|
sites[site][group][(iostandard, None)] = bits
|
||||||
|
else:
|
||||||
|
assert False, group
|
||||||
|
|
||||||
iostandard_in[in_bits].append((site, iostandard))
|
for site in sites:
|
||||||
|
for iostandard, enum in sites[site]['DRIVE']:
|
||||||
|
sites[site]['DRIVE'][(iostandard, enum)] |= sites[site]['OUT'][(
|
||||||
|
iostandard, None)]
|
||||||
|
|
||||||
if name.endswith('.OUT'):
|
for iostandard, enum in sites[site]['IN']:
|
||||||
outs[(site,
|
sites[site]['IN_ONLY'][(iostandard, enum)] -= sites[site]['IN'][(
|
||||||
iostandard)] = parse_bits(l) | in_use[(site, iostandard)]
|
iostandard, enum)]
|
||||||
|
|
||||||
if '.DRIVE.' in name and '.IN_OUT_COMMON' not in name:
|
|
||||||
drive = name.split('.')[-1]
|
|
||||||
if (site, iostandard) not in drives:
|
|
||||||
drives[(site, iostandard)] = {}
|
|
||||||
|
|
||||||
if drive not in drives[(site, iostandard)]:
|
|
||||||
drives[(site, iostandard)][drive] = {}
|
|
||||||
|
|
||||||
drives[(site, iostandard)][drive] = filter_bits(
|
|
||||||
site, parse_bits(l))
|
|
||||||
|
|
||||||
common_in_bits = {
|
|
||||||
'IOB_Y0': set(),
|
|
||||||
'IOB_Y1': set(),
|
|
||||||
}
|
|
||||||
|
|
||||||
for bits in sorted(iostandard_in.keys()):
|
|
||||||
sites, standards = zip(*iostandard_in[bits])
|
|
||||||
|
|
||||||
site = set(sites)
|
|
||||||
|
|
||||||
assert len(site) == 1, site
|
|
||||||
site = site.pop()
|
|
||||||
|
|
||||||
common_in_bits[site] |= bits
|
|
||||||
|
|
||||||
for bits in sorted(iostandard_in.keys()):
|
|
||||||
sites, standards = zip(*iostandard_in[bits])
|
|
||||||
|
|
||||||
site = set(sites)
|
|
||||||
|
|
||||||
assert len(site) == 1, site
|
|
||||||
site = site.pop()
|
|
||||||
|
|
||||||
neg_bits = set('!' + bit for bit in (common_in_bits[site] - bits))
|
|
||||||
|
|
||||||
print(
|
|
||||||
'IOB33.{}.{}.IN'.format(site, '_'.join(standards)),
|
|
||||||
' '.join(bits | neg_bits))
|
|
||||||
|
|
||||||
iodrives = {}
|
|
||||||
|
|
||||||
common_bits = {}
|
common_bits = {}
|
||||||
|
for site in sites:
|
||||||
|
for group in sites[site]:
|
||||||
|
if (site, group) not in common_bits:
|
||||||
|
common_bits[(site, group)] = set()
|
||||||
|
|
||||||
for site, iostandard in drives:
|
for bits in sites[site][group].values():
|
||||||
for drive in drives[(site, iostandard)]:
|
common_bits[(site, group)] |= bits
|
||||||
combined_bits = drives[(site, iostandard)][drive] | outs[(
|
|
||||||
site, iostandard)]
|
|
||||||
|
|
||||||
if site not in common_bits:
|
slew_in_drives = {}
|
||||||
common_bits[site] = set(common_in_only_bits[site])
|
|
||||||
|
|
||||||
common_bits[site] |= combined_bits
|
for site in sites:
|
||||||
|
common_bits[(site, 'DRIVE')] -= common_bits[(site, 'SLEW')]
|
||||||
|
common_bits[(site, 'DRIVE')] -= common_bits[(site, 'STEPDOWN')]
|
||||||
|
common_bits[(site, 'IN_ONLY')] |= common_bits[(site, 'DRIVE')]
|
||||||
|
common_bits[(site, 'IN_ONLY')] -= common_bits[(site, 'STEPDOWN')]
|
||||||
|
|
||||||
if combined_bits not in iodrives:
|
for iostandard, enum in sites[site]['DRIVE']:
|
||||||
iodrives[combined_bits] = []
|
slew_in_drive = common_bits[
|
||||||
|
(site, 'SLEW')] & sites[site]['DRIVE'][(iostandard, enum)]
|
||||||
|
if slew_in_drive:
|
||||||
|
if (site, iostandard) not in slew_in_drives:
|
||||||
|
slew_in_drives[(site, iostandard)] = set()
|
||||||
|
|
||||||
iodrives[combined_bits].append((site, iostandard, drive))
|
slew_in_drives[(site, iostandard)] |= slew_in_drive
|
||||||
|
sites[site]['DRIVE'][(iostandard, enum)] -= slew_in_drive
|
||||||
|
|
||||||
for bits in iodrives:
|
sites[site]['DRIVE'][(iostandard,
|
||||||
sites, standards, drives = zip(*iodrives[bits])
|
enum)] -= common_bits[(site, 'STEPDOWN')]
|
||||||
|
|
||||||
site = set(sites)
|
for site, iostandard in slew_in_drives:
|
||||||
|
for _, enum in sites[site]['SLEW']:
|
||||||
|
sites[site]['SLEW'][(iostandard,
|
||||||
|
enum)] |= slew_in_drives[(site, iostandard)]
|
||||||
|
|
||||||
assert len(site) == 1, site
|
for site in sites:
|
||||||
site = site.pop()
|
del sites[site]['OUT']
|
||||||
|
del sites[site]['IN_USE']
|
||||||
|
|
||||||
neg_bits = set('!' + bit for bit in (common_bits[site] - bits))
|
for site in sites:
|
||||||
|
for group in sites[site]:
|
||||||
|
common_groups = {}
|
||||||
|
|
||||||
|
# Merge features that are identical.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# IOB33.IOB_Y1.LVCMOS15.IN 38_42 39_41
|
||||||
|
# IOB33.IOB_Y1.LVCMOS18.IN 38_42 39_41
|
||||||
|
#
|
||||||
|
# Must be grouped.
|
||||||
|
for (iostandard, enum), bits in sites[site][group].items():
|
||||||
|
if bits not in common_groups:
|
||||||
|
common_groups[bits] = {
|
||||||
|
'IOSTANDARDS': set(),
|
||||||
|
'enums': set(),
|
||||||
|
}
|
||||||
|
|
||||||
|
common_groups[bits]['IOSTANDARDS'].add(iostandard)
|
||||||
|
if enum is not None:
|
||||||
|
common_groups[bits]['enums'].add(enum)
|
||||||
|
|
||||||
|
for bits, v in common_groups.items():
|
||||||
|
if v['enums']:
|
||||||
|
feature = 'IOB33.{site}.{iostandards}.{group}.{enums}'.format(
|
||||||
|
site=site,
|
||||||
|
iostandards='_'.join(sorted(v['IOSTANDARDS'])),
|
||||||
|
group=group,
|
||||||
|
enums='_'.join(sorted(v['enums'])),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
feature = 'IOB33.{site}.{iostandards}.{group}'.format(
|
||||||
|
site=site,
|
||||||
|
iostandards='_'.join(sorted(v['IOSTANDARDS'])),
|
||||||
|
group=group,
|
||||||
|
)
|
||||||
|
|
||||||
|
neg_bits = frozenset(
|
||||||
|
'!{}'.format(b)
|
||||||
|
for b in (common_bits[(site, group)] - bits))
|
||||||
print(
|
print(
|
||||||
'IOB33.{}.{}.DRIVE.{}'.format(
|
'{} {}'.format(feature, ' '.join(sorted(bits | neg_bits))))
|
||||||
site, '_'.join(sorted(set(standards))), '_'.join(
|
|
||||||
sorted(set(drives)))), ' '.join(bits | neg_bits))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,22 @@ def run():
|
||||||
io_idx = 0
|
io_idx = 0
|
||||||
|
|
||||||
iostandards = [
|
iostandards = [
|
||||||
'LVCMOS12', 'LVCMOS15', 'LVCMOS18', 'LVCMOS25', 'LVCMOS33', 'LVTTL'
|
'LVCMOS12',
|
||||||
|
'LVCMOS15',
|
||||||
|
'LVCMOS18',
|
||||||
|
'LVCMOS25',
|
||||||
|
'LVCMOS33',
|
||||||
|
'LVTTL',
|
||||||
|
'SSTL135',
|
||||||
]
|
]
|
||||||
iostandard = random.choice(iostandards)
|
iostandard = random.choice(iostandards)
|
||||||
|
|
||||||
if iostandard in ['LVTTL', 'LVCMOS18']:
|
if iostandard in ['LVTTL', 'LVCMOS18']:
|
||||||
drives = [4, 8, 12, 16, 24]
|
drives = [4, 8, 12, 16, 24]
|
||||||
elif iostandard == 'LVCMOS12':
|
elif iostandard in ['LVCMOS12']:
|
||||||
drives = [4, 8, 12]
|
drives = [4, 8, 12]
|
||||||
|
elif iostandard == 'SSTL135':
|
||||||
|
drives = None
|
||||||
else:
|
else:
|
||||||
drives = [4, 8, 12, 16]
|
drives = [4, 8, 12, 16]
|
||||||
|
|
||||||
|
|
@ -64,7 +72,26 @@ def run():
|
||||||
connects = io.StringIO()
|
connects = io.StringIO()
|
||||||
|
|
||||||
tile_params = []
|
tile_params = []
|
||||||
params = []
|
params = {
|
||||||
|
"tiles": [],
|
||||||
|
'INTERNAL_VREF': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(os.path.join(os.getenv('FUZDIR'), 'build', 'iobanks.txt')) as f:
|
||||||
|
iobanks = [int(l.strip()) for l in f]
|
||||||
|
|
||||||
|
params['iobanks'] = iobanks
|
||||||
|
|
||||||
|
if iostandard in ['SSTL135']:
|
||||||
|
for iobank in iobanks:
|
||||||
|
params['INTERNAL_VREF'][iobank] = random.choice(
|
||||||
|
(
|
||||||
|
.600,
|
||||||
|
.675,
|
||||||
|
.75,
|
||||||
|
.90,
|
||||||
|
))
|
||||||
|
|
||||||
any_idelay = False
|
any_idelay = False
|
||||||
for tile, site in gen_sites():
|
for tile, site in gen_sites():
|
||||||
p = {}
|
p = {}
|
||||||
|
|
@ -93,7 +120,10 @@ def run():
|
||||||
elif p['type'] == 'OBUF':
|
elif p['type'] == 'OBUF':
|
||||||
p['pad_wire'] = 'do[{}]'.format(o_idx)
|
p['pad_wire'] = 'do[{}]'.format(o_idx)
|
||||||
p['iwire'] = luts.get_next_output_net()
|
p['iwire'] = luts.get_next_output_net()
|
||||||
|
if drives is not None:
|
||||||
p['DRIVE'] = random.choice(drives)
|
p['DRIVE'] = random.choice(drives)
|
||||||
|
else:
|
||||||
|
p['DRIVE'] = None
|
||||||
p['SLEW'] = verilog.quote(random.choice(slews))
|
p['SLEW'] = verilog.quote(random.choice(slews))
|
||||||
|
|
||||||
o_idx += 1
|
o_idx += 1
|
||||||
|
|
@ -101,7 +131,10 @@ def run():
|
||||||
p['pad_wire'] = 'dio[{}]'.format(io_idx)
|
p['pad_wire'] = 'dio[{}]'.format(io_idx)
|
||||||
p['iwire'] = luts.get_next_output_net()
|
p['iwire'] = luts.get_next_output_net()
|
||||||
p['owire'] = luts.get_next_input_net()
|
p['owire'] = luts.get_next_input_net()
|
||||||
|
if drives is not None:
|
||||||
p['DRIVE'] = random.choice(drives)
|
p['DRIVE'] = random.choice(drives)
|
||||||
|
else:
|
||||||
|
p['DRIVE'] = None
|
||||||
p['SLEW'] = verilog.quote(random.choice(slews))
|
p['SLEW'] = verilog.quote(random.choice(slews))
|
||||||
p['tristate_wire'] = random.choice(
|
p['tristate_wire'] = random.choice(
|
||||||
('0', luts.get_next_output_net()))
|
('0', luts.get_next_output_net()))
|
||||||
|
|
@ -111,7 +144,11 @@ def run():
|
||||||
('0', luts.get_next_output_net()))
|
('0', luts.get_next_output_net()))
|
||||||
io_idx += 1
|
io_idx += 1
|
||||||
|
|
||||||
params.append(p)
|
if 'DRIVE' in p:
|
||||||
|
if p['DRIVE'] is not None:
|
||||||
|
p['DRIVE_STR'] = '.DRIVE({}),'.format(p['DRIVE'])
|
||||||
|
else:
|
||||||
|
p['DRIVE_STR'] = ''
|
||||||
|
|
||||||
if p['type'] is not None:
|
if p['type'] is not None:
|
||||||
tile_params.append(
|
tile_params.append(
|
||||||
|
|
@ -119,9 +156,14 @@ def run():
|
||||||
tile, site, p['pad_wire'], iostandard, p['DRIVE'],
|
tile, site, p['pad_wire'], iostandard, p['DRIVE'],
|
||||||
verilog.unquote(p['SLEW']) if p['SLEW'] else None,
|
verilog.unquote(p['SLEW']) if p['SLEW'] else None,
|
||||||
verilog.unquote(p['PULLTYPE'])))
|
verilog.unquote(p['PULLTYPE'])))
|
||||||
|
params['tiles'].append(p)
|
||||||
|
|
||||||
write_params(tile_params)
|
write_params(tile_params)
|
||||||
|
|
||||||
|
with open('iobank_vref.csv', 'w') as f:
|
||||||
|
for iobank, vref in params['INTERNAL_VREF'].items():
|
||||||
|
f.write('{},{}\n'.format(iobank, vref))
|
||||||
|
|
||||||
print(
|
print(
|
||||||
'''
|
'''
|
||||||
`define N_DI {n_di}
|
`define N_DI {n_di}
|
||||||
|
|
@ -141,7 +183,7 @@ module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do, inout wire [`N
|
||||||
(* KEEP, DONT_TOUCH *)
|
(* KEEP, DONT_TOUCH *)
|
||||||
LUT6 dummy_lut();''')
|
LUT6 dummy_lut();''')
|
||||||
|
|
||||||
for p in params:
|
for p in params['tiles']:
|
||||||
if p['type'] is None:
|
if p['type'] is None:
|
||||||
continue
|
continue
|
||||||
elif p['type'] == 'IBUF':
|
elif p['type'] == 'IBUF':
|
||||||
|
|
@ -173,7 +215,7 @@ module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do, inout wire [`N
|
||||||
(* KEEP, DONT_TOUCH *)
|
(* KEEP, DONT_TOUCH *)
|
||||||
OBUF #(
|
OBUF #(
|
||||||
.IOSTANDARD({IOSTANDARD}),
|
.IOSTANDARD({IOSTANDARD}),
|
||||||
.DRIVE({DRIVE}),
|
{DRIVE_STR}
|
||||||
.SLEW({SLEW})
|
.SLEW({SLEW})
|
||||||
) ibuf_{site} (
|
) ibuf_{site} (
|
||||||
.O({pad_wire}),
|
.O({pad_wire}),
|
||||||
|
|
@ -186,7 +228,7 @@ module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do, inout wire [`N
|
||||||
(* KEEP, DONT_TOUCH *)
|
(* KEEP, DONT_TOUCH *)
|
||||||
IOBUF_INTERMDISABLE #(
|
IOBUF_INTERMDISABLE #(
|
||||||
.IOSTANDARD({IOSTANDARD}),
|
.IOSTANDARD({IOSTANDARD}),
|
||||||
.DRIVE({DRIVE}),
|
{DRIVE_STR}
|
||||||
.SLEW({SLEW})
|
.SLEW({SLEW})
|
||||||
) ibuf_{site} (
|
) ibuf_{site} (
|
||||||
.IO({pad_wire}),
|
.IO({pad_wire}),
|
||||||
|
|
@ -205,7 +247,7 @@ module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do, inout wire [`N
|
||||||
|
|
||||||
print("endmodule")
|
print("endmodule")
|
||||||
|
|
||||||
with open('params.jl', 'w') as f:
|
with open('params.json', 'w') as f:
|
||||||
json.dump(params, f, indent=2)
|
json.dump(params, f, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue