mirror of https://github.com/openXC7/prjxray.git
commit
ca45656e5f
|
|
@ -1,30 +1,21 @@
|
||||||
N := 1
|
N := 50
|
||||||
include ../fuzzer.mk
|
include ../fuzzer.mk
|
||||||
|
|
||||||
SEGDATAS_L=$(addsuffix /segdata_liob33.txt,$(SPECIMENS))
|
database: build/segbits_xiob33.db
|
||||||
SEGDATAS_R=$(addsuffix /segdata_riob33.txt,$(SPECIMENS))
|
|
||||||
|
|
||||||
database: build/segbits_liob33.db build/segbits_riob33.db
|
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)
|
||||||
|
|
||||||
build/segbits_liob33.rdb: $(SPECIMENS_OK)
|
build/segbits_xiob33.db: build/segbits_xiob33.rdb process_rdb.py bits.dbf
|
||||||
${XRAY_SEGMATCH} -o build/segbits_liob33.rdb $(SEGDATAS_L)
|
python3 process_rdb.py build/segbits_xiob33.rdb > build/segbits_xiob33_processed.rdb
|
||||||
|
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in build/segbits_xiob33_processed.rdb --seg-fn-out $@
|
||||||
build/segbits_liob33.db: build/segbits_liob33.rdb
|
${XRAY_MASKMERGE} build/mask_xiob33.db $$(find -name segdata_liob33.txt) $$(find -name segdata_riob33.txt)
|
||||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
|
|
||||||
${XRAY_MASKMERGE} build/mask_liob33.db $(SEGDATAS_L)
|
|
||||||
|
|
||||||
build/segbits_riob33.rdb: $(SPECIMENS_OK)
|
|
||||||
${XRAY_SEGMATCH} -o build/segbits_riob33.rdb $(SEGDATAS_R)
|
|
||||||
|
|
||||||
build/segbits_riob33.db: build/segbits_riob33.rdb
|
|
||||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
|
|
||||||
${XRAY_MASKMERGE} build/mask_riob33.db $(SEGDATAS_R)
|
|
||||||
|
|
||||||
pushdb:
|
pushdb:
|
||||||
${XRAY_MERGEDB} liob33 build/segbits_liob33.db
|
${XRAY_MERGEDB} liob33 build/segbits_xiob33.db
|
||||||
${XRAY_MERGEDB} riob33 build/segbits_riob33.db
|
${XRAY_MERGEDB} riob33 build/segbits_xiob33.db
|
||||||
${XRAY_MERGEDB} mask_liob33 build/mask_liob33.db
|
${XRAY_MERGEDB} mask_liob33 build/mask_xiob33.db
|
||||||
${XRAY_MERGEDB} mask_riob33 build/mask_riob33.db
|
${XRAY_MERGEDB} mask_riob33 build/mask_xiob33.db
|
||||||
|
|
||||||
.PHONY: database pushdb
|
.PHONY: database pushdb
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
38_92 39_93 38_94,LIOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
38_92 39_93 38_94,IOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
||||||
38_118 38_126 39_117 39_119 39_125 39_127,LIOB33.IOB_Y0.LVCMOS25.DRIVE.12
|
38_106 38_110 39_105 39_109,IOB33.IOB_Y0.SLEW.FAST
|
||||||
38_106 38_110 39_105 39_109,LIOB33.IOB_Y0.SLEW.FAST
|
39_33 38_34 39_35,IOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
||||||
39_33 38_34 39_35,LIOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
38_18 38_22 39_17 39_21,IOB33.IOB_Y1.SLEW.FAST
|
||||||
38_00 38_02 38_08 38_10 39_01 39_09,LIOB33.IOB_Y1.LVCMOS25.DRIVE.12
|
|
||||||
38_18 38_22 39_17 39_21,LIOB33.IOB_Y1.SLEW.FAST
|
|
||||||
38_92 39_93 38_94,RIOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
|
||||||
38_118 38_126 39_117 39_119 39_125 39_127,RIOB33.IOB_Y0.LVCMOS25.DRIVE.12
|
|
||||||
38_106 38_110 39_105 39_109,RIOB33.IOB_Y0.SLEW.FAST
|
|
||||||
39_33 38_34 39_35,RIOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
|
||||||
38_00 38_02 38_08 38_10 39_01 39_09,RIOB33.IOB_Y1.LVCMOS25.DRIVE.12
|
|
||||||
38_18 38_22 39_17 39_21,RIOB33.IOB_Y1.SLEW.FAST
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
""" 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()
|
||||||
|
|
@ -2,48 +2,147 @@
|
||||||
|
|
||||||
from prjxray.segmaker import Segmaker
|
from prjxray.segmaker import Segmaker
|
||||||
from prjxray import segmaker
|
from prjxray import segmaker
|
||||||
|
from prjxray import verilog
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
segmk = Segmaker("design.bits")
|
|
||||||
|
|
||||||
print("Loading tags")
|
def bitfilter(frame, word):
|
||||||
'''
|
if frame < 26:
|
||||||
port,site,tile,pin,slew,drive,pulltype
|
return False
|
||||||
di[0],IOB_X0Y107,LIOB33_X0Y107,A21,PULLDOWN
|
|
||||||
di[10],IOB_X0Y147,LIOB33_X0Y147,F14,PULLUP
|
return True
|
||||||
'''
|
|
||||||
f = open('design.csv', 'r')
|
|
||||||
f.readline()
|
def mk_drive_opt(iostandard, drive):
|
||||||
for l in f:
|
return '{}.DRIVE.I{}'.format(iostandard, drive)
|
||||||
l = l.strip()
|
|
||||||
port, site, tile, pin, iostandard, slew, drive, pulltype = l.split(',')
|
|
||||||
|
def skip_broken_tiles(d):
|
||||||
|
""" Skip tiles that appear to have bits always set.
|
||||||
|
|
||||||
|
This is likely caused by a defect?
|
||||||
|
|
||||||
|
"""
|
||||||
|
if os.getenv('XRAY_DATABASE') == 'artix7' and d['tile'] == 'LIOB33_X0Y43':
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def drives_for_iostandard(iostandard):
|
||||||
|
if iostandard in ['LVTTL', 'LVCMOS18']:
|
||||||
|
drives = [4, 8, 12, 16, 24]
|
||||||
|
elif iostandard == 'LVCMOS12':
|
||||||
|
drives = [4, 8, 12]
|
||||||
|
else:
|
||||||
|
drives = [4, 8, 12, 16]
|
||||||
|
|
||||||
|
return drives
|
||||||
|
|
||||||
|
|
||||||
|
STEPDOWN_IOSTANDARDS = ['LVCMOS12', 'LVCMOS15', 'LVCMOS18']
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Loading tags")
|
||||||
|
segmk = Segmaker("design.bits")
|
||||||
'''
|
'''
|
||||||
LVCMOS25
|
port,site,tile,pin,slew,drive,pulltype
|
||||||
SLEW 38_82 38_86 39_81 39_85
|
di[0],IOB_X0Y107,LIOB33_X0Y107,A21,PULLDOWN
|
||||||
SLOW X X X X
|
di[10],IOB_X0Y147,LIOB33_X0Y147,F14,PULLUP
|
||||||
FAST
|
|
||||||
|
|
||||||
DRIVE 38_64 38_66 38_72 38_74 39_65 39_73
|
|
||||||
4 X X X
|
|
||||||
8 X
|
|
||||||
12
|
|
||||||
16 X X X
|
|
||||||
|
|
||||||
PULLTYPE 28 29 30
|
|
||||||
NONE X
|
|
||||||
KEEPER X X
|
|
||||||
PULLDOWN
|
|
||||||
PULLUP X X
|
|
||||||
'''
|
'''
|
||||||
if pulltype == "":
|
with open('params.jl', 'r') as f:
|
||||||
pulltype = "NONE"
|
design = json.load(f)
|
||||||
segmaker.add_site_group_zero(
|
|
||||||
segmk, site, "PULLTYPE.", ("NONE", "KEEPER", "PULLDOWN", "PULLUP"),
|
|
||||||
"PULLDOWN", pulltype)
|
|
||||||
|
|
||||||
segmaker.add_site_group_zero(
|
for d in design:
|
||||||
segmk, site, iostandard + ".DRIVE.", ("4", "8", "12", "16"), "12",
|
site = d['site']
|
||||||
drive)
|
|
||||||
segmaker.add_site_group_zero(
|
if skip_broken_tiles(d):
|
||||||
segmk, site, "SLEW.", ("SLOW", "FAST"), "FAST", slew)
|
continue
|
||||||
segmk.compile()
|
|
||||||
segmk.write()
|
iostandard = verilog.unquote(d['IOSTANDARD'])
|
||||||
|
|
||||||
|
stepdown = iostandard in STEPDOWN_IOSTANDARDS
|
||||||
|
segmk.add_site_tag(site, '_'.join(STEPDOWN_IOSTANDARDS), stepdown)
|
||||||
|
|
||||||
|
if d['type'] is None:
|
||||||
|
segmk.add_site_tag(site, 'INOUT', 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, '{}.OUT'.format(iostandard), 0)
|
||||||
|
for drive in drives_for_iostandard(iostandard):
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, '{}.DRIVE.I{}.IN_OUT_COMMON'.format(
|
||||||
|
iostandard, drive), 0)
|
||||||
|
elif d['type'] == 'IBUF':
|
||||||
|
segmk.add_site_tag(site, 'INOUT', 0)
|
||||||
|
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), 0)
|
||||||
|
for drive in drives_for_iostandard(iostandard):
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, '{}.DRIVE.I{}.IN_OUT_COMMON'.format(
|
||||||
|
iostandard, drive), 1)
|
||||||
|
elif d['type'] == 'OBUF':
|
||||||
|
segmk.add_site_tag(site, 'INOUT', 0)
|
||||||
|
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
||||||
|
segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
|
||||||
|
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':
|
||||||
|
segmk.add_site_tag(site, 'INOUT', 1)
|
||||||
|
segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
|
||||||
|
segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
|
||||||
|
|
||||||
|
if d['type'] is not None:
|
||||||
|
segmaker.add_site_group_zero(
|
||||||
|
segmk, site, "PULLTYPE.",
|
||||||
|
("NONE", "KEEPER", "PULLDOWN", "PULLUP"), "PULLDOWN",
|
||||||
|
verilog.unquote(d['PULLTYPE']))
|
||||||
|
|
||||||
|
if d['type'] == 'IBUF' or d['type'] is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
drive_opts = set()
|
||||||
|
for opt in ("LVCMOS25", "LVCMOS33", "LVCMOS18", "LVCMOS15",
|
||||||
|
"LVCMOS12", 'LVTTL'):
|
||||||
|
for drive_opt in ("4", "8", "12", "16", "24"):
|
||||||
|
if drive_opt == "16" and opt == "LVCMOS12":
|
||||||
|
continue
|
||||||
|
|
||||||
|
if drive_opt == "24" and opt not in ["LVCMOS18", 'LVTTL']:
|
||||||
|
continue
|
||||||
|
|
||||||
|
drive_opts.add(mk_drive_opt(opt, drive_opt))
|
||||||
|
|
||||||
|
segmaker.add_site_group_zero(
|
||||||
|
segmk, site, '', drive_opts, mk_drive_opt('LVCMOS25', '12'),
|
||||||
|
mk_drive_opt(iostandard, d['DRIVE']))
|
||||||
|
|
||||||
|
segmaker.add_site_group_zero(
|
||||||
|
segmk, site, "SLEW.", ("SLOW", "FAST"), "FAST",
|
||||||
|
verilog.unquote(d['SLEW']))
|
||||||
|
|
||||||
|
if 'ibufdisable_wire' in d:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IBUFDISABLE.I', d['ibufdisable_wire'] != '0')
|
||||||
|
|
||||||
|
if 'intermdisable_wire' in d:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'INTERMDISABLE.I', d['intermdisable_wire'] != '0')
|
||||||
|
|
||||||
|
segmk.compile(bitfilter=bitfilter)
|
||||||
|
segmk.write(allow_empty=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
source ${XRAY_DIR}/utils/top_generate.sh
|
|
||||||
|
|
||||||
|
|
@ -19,6 +19,8 @@ proc load_pin_lines {} {
|
||||||
# IOB_X0Y129 do[0] output
|
# IOB_X0Y129 do[0] output
|
||||||
|
|
||||||
set fp [open "params.csv" r]
|
set fp [open "params.csv" r]
|
||||||
|
gets $fp line
|
||||||
|
|
||||||
set pin_lines {}
|
set pin_lines {}
|
||||||
for {gets $fp line} {$line != ""} {gets $fp line} {
|
for {gets $fp line} {$line != ""} {gets $fp line} {
|
||||||
lappend pin_lines [split $line ","]
|
lappend pin_lines [split $line ","]
|
||||||
|
|
@ -31,51 +33,46 @@ proc loc_pins {} {
|
||||||
set pin_lines [load_pin_lines]
|
set pin_lines [load_pin_lines]
|
||||||
set io_pin_sites [make_io_pin_sites]
|
set io_pin_sites [make_io_pin_sites]
|
||||||
|
|
||||||
set fp [open "design.csv" w]
|
|
||||||
puts $fp "port,site,tile,pin,iostandard,slew,drive,pulltype"
|
|
||||||
|
|
||||||
puts "Looping"
|
puts "Looping"
|
||||||
for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
|
for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
|
||||||
set line [lindex $pin_lines $idx]
|
set line [lindex $pin_lines $idx]
|
||||||
puts "$line"
|
puts "$line"
|
||||||
|
|
||||||
set site_str [lindex $line 0]
|
set site_str [lindex $line 1]
|
||||||
set pin_str [lindex $line 1]
|
set pin_str [lindex $line 2]
|
||||||
set io [lindex $line 2]
|
set iostandard [lindex $line 3]
|
||||||
set cell_str [lindex $line 3]
|
set drive [lindex $line 4]
|
||||||
|
set slew [lindex $line 5]
|
||||||
|
set pulltype [lindex $line 6]
|
||||||
|
|
||||||
# Have: site
|
# Have: site
|
||||||
# Want: pin for site
|
# Want: pin for site
|
||||||
|
|
||||||
set site [get_sites $site_str]
|
set site [get_sites $site_str]
|
||||||
set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
|
set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
|
||||||
# set port [get_ports -of_objects $site]
|
# set port [get_ports -of_objects $site]
|
||||||
set port [get_ports $pin_str]
|
set port [get_ports $pin_str]
|
||||||
set tile [get_tiles -of_objects $site]
|
set tile [get_tiles -of_objects $site]
|
||||||
|
|
||||||
set pin [dict get $io_pin_sites $site]
|
set pin [dict get $io_pin_sites $site]
|
||||||
|
|
||||||
set iostandard_val "LVCMOS25"
|
set props {}
|
||||||
set_property -dict "PACKAGE_PIN $pin IOSTANDARD $iostandard_val" $port
|
lappend props PACKAGE_PIN $pin
|
||||||
|
lappend props IOSTANDARD $iostandard
|
||||||
|
lappend props PULLTYPE $pulltype
|
||||||
|
|
||||||
set pulltype "NONE PULLUP PULLDOWN KEEPER"
|
if {$drive != "None"} {
|
||||||
set pulltype_val [randsample_list 1 $pulltype]
|
lappend props DRIVE $drive
|
||||||
if { $pulltype_val == "NONE" } {
|
|
||||||
set pulltype_val ""
|
|
||||||
}
|
}
|
||||||
set_property PULLTYPE $pulltype_val $port
|
|
||||||
|
|
||||||
if {$io == "input"} continue
|
if {$slew != "None"} {
|
||||||
|
lappend props SLEW $slew
|
||||||
|
}
|
||||||
|
|
||||||
set drive "4 8 12 16"
|
puts $props
|
||||||
set drive_val [lindex $drive [expr {$idx % 4}]]
|
|
||||||
set_property DRIVE $drive_val $port
|
|
||||||
|
|
||||||
set slew "SLOW FAST"
|
set_property -dict "$props" $port
|
||||||
set slew_val [lindex $slew [expr {($idx + ($idx / 4)) % 2}]]
|
|
||||||
set_property SLEW $slew_val $port
|
|
||||||
|
|
||||||
puts $fp "$port,$site,$tile,$pin,$iostandard_val,$slew_val,$drive_val,$pulltype_val"
|
|
||||||
}
|
}
|
||||||
close $fp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc run {} {
|
proc run {} {
|
||||||
|
|
@ -83,17 +80,14 @@ proc run {} {
|
||||||
read_verilog top.v
|
read_verilog top.v
|
||||||
synth_design -top top
|
synth_design -top top
|
||||||
|
|
||||||
# Mostly doesn't matter since IOB are special, but add anyway
|
|
||||||
create_pblock roi
|
|
||||||
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
|
|
||||||
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
|
|
||||||
|
|
||||||
loc_pins
|
loc_pins
|
||||||
|
|
||||||
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]
|
||||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||||
set_param tcl.collectionResultDisplayLimit 0
|
set_property IS_ENABLED 0 [get_drc_checks {REQP-79}]
|
||||||
|
|
||||||
|
write_checkpoint -force design_pre_place.dcp
|
||||||
|
|
||||||
place_design
|
place_design
|
||||||
route_design
|
route_design
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,193 @@
|
||||||
|
""" IOB bits are more complicated than can be easily expressed to segmaker.
|
||||||
|
|
||||||
|
There are couple cases that need to be handled here:
|
||||||
|
|
||||||
|
- There are some bits that are always set for IN-only ports, but are cleared
|
||||||
|
selectively for OUT and INOUT ports.
|
||||||
|
- There are bits per each IOSTANDARD, in addition to drive patterns. These
|
||||||
|
can be merged to provide unique "(IOSTANDARD, DRIVE)" bit sets.
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
def get_name(l):
|
||||||
|
parts = l.strip().split(' ')
|
||||||
|
return parts[0]
|
||||||
|
|
||||||
|
|
||||||
|
def get_site(l):
|
||||||
|
return get_name(l).split('.')[1]
|
||||||
|
|
||||||
|
|
||||||
|
def parse_bits(l):
|
||||||
|
parts = l.strip().split(' ')
|
||||||
|
if parts[1] == '<0':
|
||||||
|
return frozenset()
|
||||||
|
else:
|
||||||
|
return frozenset(parts[1:])
|
||||||
|
|
||||||
|
|
||||||
|
def filter_bits(site, bits):
|
||||||
|
""" Seperate top and bottom bits.
|
||||||
|
|
||||||
|
Some IOSTANDARD bits are tile wide, but really only apply to a half.
|
||||||
|
It is hard to write a fuzzer for this, but it is easy to filter by site,
|
||||||
|
and all bits appear to have a nice hard halve seperatation in the bitidx.
|
||||||
|
"""
|
||||||
|
if site == 'IOB_Y0':
|
||||||
|
min_bitidx = 64
|
||||||
|
max_bitidx = 127
|
||||||
|
elif site == 'IOB_Y1':
|
||||||
|
min_bitidx = 0
|
||||||
|
max_bitidx = 63
|
||||||
|
else:
|
||||||
|
assert False, site
|
||||||
|
|
||||||
|
def inner():
|
||||||
|
for bit in bits:
|
||||||
|
bitidx = int(bit.split('_')[1])
|
||||||
|
|
||||||
|
if bitidx < min_bitidx or bitidx > max_bitidx:
|
||||||
|
continue
|
||||||
|
|
||||||
|
yield bit
|
||||||
|
|
||||||
|
return frozenset(inner())
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Convert IOB rdb into good rdb."
|
||||||
|
"")
|
||||||
|
parser.add_argument('input_rdb')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
iostandard_lines = []
|
||||||
|
with open(args.input_rdb) as f:
|
||||||
|
for l in f:
|
||||||
|
if ('.LVCMOS' in l or '.LVTTL' in l) and 'IOB_' in l:
|
||||||
|
iostandard_lines.append(l)
|
||||||
|
else:
|
||||||
|
print(l.strip())
|
||||||
|
|
||||||
|
common_in_only_bits = {
|
||||||
|
'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:
|
||||||
|
name = get_name(l)
|
||||||
|
site = get_site(l)
|
||||||
|
iostandard = name.split('.')[2]
|
||||||
|
|
||||||
|
if name.endswith('.IN_USE'):
|
||||||
|
in_use[(site, iostandard)] = parse_bits(l)
|
||||||
|
|
||||||
|
for l in iostandard_lines:
|
||||||
|
name = get_name(l)
|
||||||
|
site = get_site(l)
|
||||||
|
iostandard = name.split('.')[2]
|
||||||
|
|
||||||
|
if name.endswith('.IN'):
|
||||||
|
in_bits = parse_bits(l) | in_use[(site, iostandard)]
|
||||||
|
|
||||||
|
if in_bits not in iostandard_in:
|
||||||
|
iostandard_in[in_bits] = []
|
||||||
|
|
||||||
|
iostandard_in[in_bits].append((site, iostandard))
|
||||||
|
|
||||||
|
if name.endswith('.OUT'):
|
||||||
|
outs[(site,
|
||||||
|
iostandard)] = parse_bits(l) | in_use[(site, iostandard)]
|
||||||
|
|
||||||
|
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 = {}
|
||||||
|
|
||||||
|
for site, iostandard in drives:
|
||||||
|
for drive in drives[(site, iostandard)]:
|
||||||
|
combined_bits = drives[(site, iostandard)][drive] | outs[(
|
||||||
|
site, iostandard)]
|
||||||
|
|
||||||
|
if site not in common_bits:
|
||||||
|
common_bits[site] = set(common_in_only_bits[site])
|
||||||
|
|
||||||
|
common_bits[site] |= combined_bits
|
||||||
|
|
||||||
|
if combined_bits not in iodrives:
|
||||||
|
iodrives[combined_bits] = []
|
||||||
|
|
||||||
|
iodrives[combined_bits].append((site, iostandard, drive))
|
||||||
|
|
||||||
|
for bits in iodrives:
|
||||||
|
sites, standards, drives = zip(*iodrives[bits])
|
||||||
|
|
||||||
|
site = set(sites)
|
||||||
|
|
||||||
|
assert len(site) == 1, site
|
||||||
|
site = site.pop()
|
||||||
|
|
||||||
|
neg_bits = set('!' + bit for bit in (common_bits[site] - bits))
|
||||||
|
|
||||||
|
print(
|
||||||
|
'IOB33.{}.{}.DRIVE.{}'.format(
|
||||||
|
site, '_'.join(sorted(set(standards))), '_'.join(
|
||||||
|
sorted(set(drives)))), ' '.join(bits | neg_bits))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
'''
|
import json
|
||||||
Generate a primitive to place at every I/O
|
import io
|
||||||
Unlike CLB tests, the LFSR for this is inside the ROI, not driving it
|
|
||||||
'''
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
random.seed(int(os.getenv("SEED"), 16))
|
random.seed(int(os.getenv("SEED"), 16))
|
||||||
from prjxray import util
|
from prjxray import util
|
||||||
|
from prjxray import lut_maker
|
||||||
from prjxray import verilog
|
from prjxray import verilog
|
||||||
from prjxray.db import Database
|
from prjxray.db import Database
|
||||||
|
|
||||||
|
|
||||||
def gen_iobs():
|
def gen_sites():
|
||||||
'''
|
'''
|
||||||
IOB33S: main IOB of a diff pair
|
IOB33S: main IOB of a diff pair
|
||||||
IOB33M: secondary IOB of a diff pair
|
IOB33M: secondary IOB of a diff pair
|
||||||
|
|
@ -26,124 +24,189 @@ def gen_iobs():
|
||||||
|
|
||||||
for site_name, site_type in gridinfo.sites.items():
|
for site_name, site_type in gridinfo.sites.items():
|
||||||
if site_type in ['IOB33S', 'IOB33M']:
|
if site_type in ['IOB33S', 'IOB33M']:
|
||||||
yield site_name, site_type
|
yield tile_name, site_name
|
||||||
|
|
||||||
|
|
||||||
def write_pins(ports):
|
def write_params(params):
|
||||||
pinstr = ''
|
pinstr = 'tile,site,pin,iostandard,drive,slew\n'
|
||||||
for site, (name, dir_, cell) in sorted(ports.items(), key=lambda x: x[1]):
|
for vals in params:
|
||||||
# pinstr += 'set_property -dict "PACKAGE_PIN %s IOSTANDARD LVCMOS33" [get_ports %s]' % (packpin, port)
|
pinstr += ','.join(map(str, vals)) + '\n'
|
||||||
pinstr += '%s,%s,%s,%s\n' % (site, name, dir_, cell)
|
|
||||||
open('params.csv', 'w').write(pinstr)
|
open('params.csv', 'w').write(pinstr)
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
# All possible values
|
tile_types = [
|
||||||
iosites = {}
|
'IBUF', 'OBUF', 'IOBUF_INTERMDISABLE', None, None, None, None, None
|
||||||
for site_name, site_type in gen_iobs():
|
]
|
||||||
iosites[site_name] = site_type
|
|
||||||
|
|
||||||
# Assigned in this design
|
i_idx = 0
|
||||||
ports = {}
|
o_idx = 0
|
||||||
DIN_N = 0
|
io_idx = 0
|
||||||
DOUT_N = 0
|
|
||||||
|
|
||||||
def remain_sites():
|
iostandards = [
|
||||||
return set(iosites.keys()) - set(ports.keys())
|
'LVCMOS12', 'LVCMOS15', 'LVCMOS18', 'LVCMOS25', 'LVCMOS33', 'LVTTL'
|
||||||
|
]
|
||||||
|
iostandard = random.choice(iostandards)
|
||||||
|
|
||||||
def rand_site():
|
if iostandard in ['LVTTL', 'LVCMOS18']:
|
||||||
'''Get a random, unused site'''
|
drives = [4, 8, 12, 16, 24]
|
||||||
return random.choice(list(remain_sites()))
|
elif iostandard == 'LVCMOS12':
|
||||||
|
drives = [4, 8, 12]
|
||||||
|
else:
|
||||||
|
drives = [4, 8, 12, 16]
|
||||||
|
|
||||||
def assign_i(site, name):
|
slews = ['FAST', 'SLOW']
|
||||||
nonlocal DIN_N
|
pulls = ["NONE", "KEEPER", "PULLDOWN", "PULLUP"]
|
||||||
|
|
||||||
assert site not in ports
|
luts = lut_maker.LutMaker()
|
||||||
cell = "di_bufs[%u].ibuf" % DIN_N
|
|
||||||
DIN_N += 1
|
|
||||||
ports[site] = (name, 'input', cell)
|
|
||||||
|
|
||||||
def assign_o(site, name):
|
connects = io.StringIO()
|
||||||
nonlocal DOUT_N
|
|
||||||
|
|
||||||
assert site not in ports
|
tile_params = []
|
||||||
cell = "do_bufs[%u].obuf" % DOUT_N
|
params = []
|
||||||
DOUT_N += 1
|
any_idelay = False
|
||||||
ports[site] = (name, 'output', cell)
|
for tile, site in gen_sites():
|
||||||
|
p = {}
|
||||||
|
p['tile'] = tile
|
||||||
|
p['site'] = site
|
||||||
|
p['type'] = random.choice(tile_types)
|
||||||
|
p['IOSTANDARD'] = verilog.quote(iostandard)
|
||||||
|
p['PULLTYPE'] = verilog.quote(random.choice(pulls))
|
||||||
|
|
||||||
# Assign at least one di and one do
|
if p['type'] is None:
|
||||||
assign_i(rand_site(), 'di[0]')
|
p['pad_wire'] = None
|
||||||
assign_o(rand_site(), 'do[0]')
|
elif p['type'] == 'IBUF':
|
||||||
# Now assign the rest randomly
|
p['pad_wire'] = 'di[{}]'.format(i_idx)
|
||||||
while len(remain_sites()):
|
p['IDELAY_ONLY'] = random.randint(0, 1)
|
||||||
assign_o(rand_site(), 'do[%u]' % DOUT_N)
|
if not p['IDELAY_ONLY']:
|
||||||
|
p['owire'] = luts.get_next_input_net()
|
||||||
|
else:
|
||||||
|
any_idelay = True
|
||||||
|
p['owire'] = 'idelay_{site}'.format(**p)
|
||||||
|
|
||||||
write_pins(ports)
|
p['DRIVE'] = None
|
||||||
|
p['SLEW'] = None
|
||||||
|
p['IBUF_LOW_PWR'] = random.randint(0, 1)
|
||||||
|
|
||||||
|
i_idx += 1
|
||||||
|
elif p['type'] == 'OBUF':
|
||||||
|
p['pad_wire'] = 'do[{}]'.format(o_idx)
|
||||||
|
p['iwire'] = luts.get_next_output_net()
|
||||||
|
p['DRIVE'] = random.choice(drives)
|
||||||
|
p['SLEW'] = verilog.quote(random.choice(slews))
|
||||||
|
|
||||||
|
o_idx += 1
|
||||||
|
elif p['type'] == 'IOBUF_INTERMDISABLE':
|
||||||
|
p['pad_wire'] = 'dio[{}]'.format(io_idx)
|
||||||
|
p['iwire'] = luts.get_next_output_net()
|
||||||
|
p['owire'] = luts.get_next_input_net()
|
||||||
|
p['DRIVE'] = random.choice(drives)
|
||||||
|
p['SLEW'] = verilog.quote(random.choice(slews))
|
||||||
|
p['tristate_wire'] = random.choice(
|
||||||
|
('0', luts.get_next_output_net()))
|
||||||
|
p['ibufdisable_wire'] = random.choice(
|
||||||
|
('0', luts.get_next_output_net()))
|
||||||
|
p['intermdisable_wire'] = random.choice(
|
||||||
|
('0', luts.get_next_output_net()))
|
||||||
|
io_idx += 1
|
||||||
|
|
||||||
|
params.append(p)
|
||||||
|
|
||||||
|
if p['type'] is not None:
|
||||||
|
tile_params.append(
|
||||||
|
(
|
||||||
|
tile, site, p['pad_wire'], iostandard, p['DRIVE'],
|
||||||
|
verilog.unquote(p['SLEW']) if p['SLEW'] else None,
|
||||||
|
verilog.unquote(p['PULLTYPE'])))
|
||||||
|
|
||||||
|
write_params(tile_params)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
'''
|
'''
|
||||||
`define N_DI %u
|
`define N_DI {n_di}
|
||||||
`define N_DO %u
|
`define N_DO {n_do}
|
||||||
|
`define N_DIO {n_dio}
|
||||||
|
|
||||||
module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do, inout wire [`N_DIO-1:0] dio);
|
||||||
genvar i;
|
'''.format(n_di=i_idx, n_do=o_idx, n_dio=io_idx))
|
||||||
|
|
||||||
//Instantiate BUFs so we can LOC them
|
if any_idelay:
|
||||||
|
print('''
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
IDELAYCTRL();''')
|
||||||
|
|
||||||
wire [`N_DI-1:0] di_buf;
|
# Always output a LUT6 to make placer happy.
|
||||||
generate
|
print('''
|
||||||
for (i = 0; i < `N_DI; i = i+1) begin:di_bufs
|
(* KEEP, DONT_TOUCH *)
|
||||||
IBUF ibuf(.I(di[i]), .O(di_buf[i]));
|
LUT6 dummy_lut();''')
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
wire [`N_DO-1:0] do_unbuf;
|
for p in params:
|
||||||
generate
|
if p['type'] is None:
|
||||||
for (i = 0; i < `N_DO; i = i+1) begin:do_bufs
|
continue
|
||||||
OBUF obuf(.I(do_unbuf[i]), .O(do[i]));
|
elif p['type'] == 'IBUF':
|
||||||
end
|
print(
|
||||||
endgenerate
|
'''
|
||||||
|
wire idelay_{site};
|
||||||
|
|
||||||
roi roi(.di(di_buf), .do(do_unbuf));
|
(* KEEP, DONT_TOUCH *)
|
||||||
endmodule
|
IBUF #(
|
||||||
|
.IBUF_LOW_PWR({IBUF_LOW_PWR}),
|
||||||
|
.IOSTANDARD({IOSTANDARD})
|
||||||
|
) ibuf_{site} (
|
||||||
|
.I({pad_wire}),
|
||||||
|
.O({owire})
|
||||||
|
);'''.format(**p),
|
||||||
|
file=connects)
|
||||||
|
if p['IDELAY_ONLY']:
|
||||||
|
print(
|
||||||
|
"""
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
IDELAYE2 idelay_site_{site} (
|
||||||
|
.IDATAIN(idelay_{site})
|
||||||
|
);""".format(**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
//Arbitrary terminate into LUTs
|
elif p['type'] == 'OBUF':
|
||||||
module roi(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
print(
|
||||||
genvar i;
|
'''
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
OBUF #(
|
||||||
|
.IOSTANDARD({IOSTANDARD}),
|
||||||
|
.DRIVE({DRIVE}),
|
||||||
|
.SLEW({SLEW})
|
||||||
|
) ibuf_{site} (
|
||||||
|
.O({pad_wire}),
|
||||||
|
.I({iwire})
|
||||||
|
);'''.format(**p),
|
||||||
|
file=connects)
|
||||||
|
elif p['type'] == 'IOBUF_INTERMDISABLE':
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
IOBUF_INTERMDISABLE #(
|
||||||
|
.IOSTANDARD({IOSTANDARD}),
|
||||||
|
.DRIVE({DRIVE}),
|
||||||
|
.SLEW({SLEW})
|
||||||
|
) ibuf_{site} (
|
||||||
|
.IO({pad_wire}),
|
||||||
|
.I({iwire}),
|
||||||
|
.O({owire}),
|
||||||
|
.T({tristate_wire}),
|
||||||
|
.IBUFDISABLE({ibufdisable_wire}),
|
||||||
|
.INTERMDISABLE({intermdisable_wire})
|
||||||
|
);'''.format(**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
generate
|
for l in luts.create_wires_and_luts():
|
||||||
for (i = 0; i < `N_DI; i = i+1) begin:dis
|
print(l)
|
||||||
(* KEEP, DONT_TOUCH *)
|
|
||||||
LUT6 #(
|
|
||||||
.INIT(64'h8000_0000_0000_0001)
|
|
||||||
) lut (
|
|
||||||
.I0(di[i]),
|
|
||||||
.I1(di[i]),
|
|
||||||
.I2(di[i]),
|
|
||||||
.I3(di[i]),
|
|
||||||
.I4(di[i]),
|
|
||||||
.I5(di[i]),
|
|
||||||
.O());
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
generate
|
print(connects.getvalue())
|
||||||
for (i = 0; i < `N_DO; i = i+1) begin:dos
|
|
||||||
(* KEEP, DONT_TOUCH *)
|
print("endmodule")
|
||||||
LUT6 #(
|
|
||||||
.INIT(64'h8000_0000_0000_0001)
|
with open('params.jl', 'w') as f:
|
||||||
) lut (
|
json.dump(params, f, indent=2)
|
||||||
.I0(),
|
|
||||||
.I1(),
|
|
||||||
.I2(),
|
|
||||||
.I3(),
|
|
||||||
.I4(),
|
|
||||||
.I5(),
|
|
||||||
.O(do[i]));
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
|
||||||
''' % (DIN_N, DOUT_N))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
N := 1
|
|
||||||
include ../fuzzer.mk
|
|
||||||
|
|
||||||
SEGDATAS=$(addsuffix /segdata_liob33.txt,$(SPECIMENS))
|
|
||||||
|
|
||||||
database: build/segbits_liob33.db
|
|
||||||
|
|
||||||
build/segbits_liob33.rdb: $(SPECIMENS_OK)
|
|
||||||
${XRAY_SEGMATCH} -c -1 -o build/segbits_liob33.rdb $(SEGDATAS)
|
|
||||||
|
|
||||||
build/segbits_liob33.db: build/segbits_liob33.rdb
|
|
||||||
python3 ${XRAY_DIR}/utils/groupmask.py $^ $@
|
|
||||||
${XRAY_MASKMERGE} build/mask_liob33.db $(SEGDATAS)
|
|
||||||
|
|
||||||
pushdb:
|
|
||||||
${XRAY_MERGEDB} liob33 build/segbits_liob33.db
|
|
||||||
${XRAY_MERGEDB} mask_liob33 build/mask_liob33.db
|
|
||||||
|
|
||||||
.PHONY: database pushdb
|
|
||||||
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
from prjxray.segmaker import Segmaker
|
|
||||||
from prjxray import segmaker
|
|
||||||
|
|
||||||
segmk = Segmaker("design.bits")
|
|
||||||
|
|
||||||
print("Loading params")
|
|
||||||
f = open('params.csv', 'r')
|
|
||||||
f.readline()
|
|
||||||
for l in f:
|
|
||||||
l = l.strip()
|
|
||||||
site, name, dir_, cell = l.split(',')
|
|
||||||
segmaker.add_site_group_zero(
|
|
||||||
segmk, site, "MACRO.", ("INPUT", "OUTPUT"), "", dir_.upper())
|
|
||||||
|
|
||||||
segmk.compile()
|
|
||||||
segmk.write()
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
source ${XRAY_DIR}/utils/top_generate.sh
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
LIOB33.IOB_Y1.MACRO
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
||||||
'''
|
|
||||||
Generate a primitive to place at every I/O
|
|
||||||
Unlike CLB tests, the LFSR for this is inside the ROI, not driving it
|
|
||||||
'''
|
|
||||||
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
random.seed(int(os.getenv("SEED"), 16))
|
|
||||||
from prjxray import util
|
|
||||||
from prjxray import verilog
|
|
||||||
|
|
||||||
|
|
||||||
def gen_iobs():
|
|
||||||
'''
|
|
||||||
IOB33S: main IOB of a diff pair
|
|
||||||
IOB33M: secondary IOB of a diff pair
|
|
||||||
IOB33: not a diff pair. Relatively rare (at least in ROI...2 of them?)
|
|
||||||
Focus on IOB33S to start
|
|
||||||
'''
|
|
||||||
for _tile_name, site_name, site_type in util.get_roi().gen_sites(
|
|
||||||
#['IOB33', 'IOB33S', 'IOB33M']):
|
|
||||||
['IOB33S']):
|
|
||||||
yield site_name, site_type
|
|
||||||
|
|
||||||
|
|
||||||
def write_pins(ports):
|
|
||||||
pinstr = 'site,name,dir,cell\n'
|
|
||||||
for site, (name, dir_, cell) in sorted(ports.items(), key=lambda x: x[1]):
|
|
||||||
# pinstr += 'set_property -dict "PACKAGE_PIN %s IOSTANDARD LVCMOS33" [get_ports %s]' % (packpin, port)
|
|
||||||
pinstr += '%s,%s,%s,%s\n' % (site, name, dir_, cell)
|
|
||||||
open('params.csv', 'w').write(pinstr)
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
# All possible values
|
|
||||||
iosites = {}
|
|
||||||
for site_name, site_type in gen_iobs():
|
|
||||||
iosites[site_name] = site_type
|
|
||||||
|
|
||||||
# Assigned in this design
|
|
||||||
ports = {}
|
|
||||||
DIN_N = 0
|
|
||||||
DOUT_N = 0
|
|
||||||
|
|
||||||
def remain_sites():
|
|
||||||
return set(iosites.keys()) - set(ports.keys())
|
|
||||||
|
|
||||||
def rand_site():
|
|
||||||
'''Get a random, unused site'''
|
|
||||||
return random.choice(list(remain_sites()))
|
|
||||||
|
|
||||||
def assign_i(site, name):
|
|
||||||
nonlocal DIN_N
|
|
||||||
|
|
||||||
assert site not in ports
|
|
||||||
cell = "di_bufs[%u].ibuf" % DIN_N
|
|
||||||
DIN_N += 1
|
|
||||||
ports[site] = (name, 'input', cell)
|
|
||||||
|
|
||||||
def assign_o(site, name):
|
|
||||||
nonlocal DOUT_N
|
|
||||||
|
|
||||||
assert site not in ports
|
|
||||||
cell = "do_bufs[%u].obuf" % DOUT_N
|
|
||||||
DOUT_N += 1
|
|
||||||
ports[site] = (name, 'output', cell)
|
|
||||||
|
|
||||||
# Assign at least one di and one do
|
|
||||||
assign_i(rand_site(), 'di[0]')
|
|
||||||
assign_o(rand_site(), 'do[0]')
|
|
||||||
# Now assign the rest randomly
|
|
||||||
while len(remain_sites()):
|
|
||||||
site = rand_site()
|
|
||||||
choice = random.randint(0, 2)
|
|
||||||
if choice == 0:
|
|
||||||
assign_i(site, 'di[%u]' % DIN_N)
|
|
||||||
elif choice == 1:
|
|
||||||
assign_o(site, 'do[%u]' % DOUT_N)
|
|
||||||
# Empty to provide a reference for no instance
|
|
||||||
else:
|
|
||||||
ports[site] = ("", "", "")
|
|
||||||
|
|
||||||
write_pins(ports)
|
|
||||||
|
|
||||||
print(
|
|
||||||
'''
|
|
||||||
`define N_DI %u
|
|
||||||
`define N_DO %u
|
|
||||||
|
|
||||||
module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
|
||||||
genvar i;
|
|
||||||
|
|
||||||
//Instantiate BUFs so we can LOC them
|
|
||||||
|
|
||||||
wire [`N_DI-1:0] di_buf;
|
|
||||||
generate
|
|
||||||
for (i = 0; i < `N_DI; i = i+1) begin:di_bufs
|
|
||||||
IBUF ibuf(.I(di[i]), .O(di_buf[i]));
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
wire [`N_DO-1:0] do_unbuf;
|
|
||||||
generate
|
|
||||||
for (i = 0; i < `N_DO; i = i+1) begin:do_bufs
|
|
||||||
OBUF obuf(.I(do_unbuf[i]), .O(do[i]));
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
roi roi(.di(di_buf), .do(do_unbuf));
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
//Arbitrary terminate into LUTs
|
|
||||||
module roi(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
|
||||||
genvar i;
|
|
||||||
|
|
||||||
generate
|
|
||||||
for (i = 0; i < `N_DI; i = i+1) begin:dis
|
|
||||||
(* KEEP, DONT_TOUCH *)
|
|
||||||
LUT6 #(
|
|
||||||
.INIT(64'h8000_0000_0000_0001)
|
|
||||||
) lut (
|
|
||||||
.I0(di[i]),
|
|
||||||
.I1(di[i]),
|
|
||||||
.I2(di[i]),
|
|
||||||
.I3(di[i]),
|
|
||||||
.I4(di[i]),
|
|
||||||
.I5(di[i]),
|
|
||||||
.O());
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
generate
|
|
||||||
for (i = 0; i < `N_DO; i = i+1) begin:dos
|
|
||||||
(* KEEP, DONT_TOUCH *)
|
|
||||||
LUT6 #(
|
|
||||||
.INIT(64'h8000_0000_0000_0001)
|
|
||||||
) lut (
|
|
||||||
.I0(),
|
|
||||||
.I1(),
|
|
||||||
.I2(),
|
|
||||||
.I3(),
|
|
||||||
.I4(),
|
|
||||||
.I5(),
|
|
||||||
.O(do[i]));
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
|
||||||
''' % (DIN_N, DOUT_N))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
run()
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
N := 30
|
||||||
|
include ../fuzzer.mk
|
||||||
|
|
||||||
|
database: build/segbits_xiob33.db
|
||||||
|
|
||||||
|
build/segbits_xiob33.rdb: $(SPECIMENS_OK)
|
||||||
|
${XRAY_SEGMATCH} -c 6 -o build/segbits_xiob33.rdb $$(find -name segdata_liob33.txt) $$(find -name segdata_riob33.txt)
|
||||||
|
|
||||||
|
build/segbits_xiob33.db: build/segbits_xiob33.rdb
|
||||||
|
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
|
||||||
|
${XRAY_MASKMERGE} build/mask_xiob33.db $$(find -name segdata_liob33.txt) $$(find -name segdata_riob33.txt)
|
||||||
|
|
||||||
|
pushdb:
|
||||||
|
${XRAY_MERGEDB} liob33 build/segbits_xiob33.db
|
||||||
|
${XRAY_MERGEDB} riob33 build/segbits_xiob33.db
|
||||||
|
${XRAY_MERGEDB} mask_liob33 build/mask_xiob33.db
|
||||||
|
${XRAY_MERGEDB} mask_riob33 build/mask_xiob33.db
|
||||||
|
|
||||||
|
.PHONY: database pushdb
|
||||||
|
|
||||||
|
|
@ -0,0 +1,190 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from prjxray.segmaker import Segmaker
|
||||||
|
from prjxray import verilog
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def handle_data_width(segmk, d):
|
||||||
|
if 'DATA_WIDTH' not in d:
|
||||||
|
return
|
||||||
|
|
||||||
|
if d['DATA_RATE'] == 'DDR':
|
||||||
|
return
|
||||||
|
|
||||||
|
for opt in [2, 3, 4, 5, 6, 7, 8, 10, 14]:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
d['site'], 'ISERDES.DATA_WIDTH.{}'.format(opt),
|
||||||
|
d['DATA_WIDTH'] == opt)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_data_rate(segmk, d):
|
||||||
|
if 'DATA_WIDTH' not in d:
|
||||||
|
return
|
||||||
|
|
||||||
|
for opt in ['SDR', 'DDR']:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
d['site'], 'ISERDES.DATA_RATE.{}'.format(opt),
|
||||||
|
verilog.unquote(d['DATA_RATE']) == opt)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Loading tags")
|
||||||
|
segmk = Segmaker("design.bits")
|
||||||
|
|
||||||
|
with open('params.jl', 'r') as f:
|
||||||
|
design = json.load(f)
|
||||||
|
|
||||||
|
for d in design:
|
||||||
|
site = d['site']
|
||||||
|
|
||||||
|
handle_data_width(segmk, d)
|
||||||
|
handle_data_rate(segmk, d)
|
||||||
|
|
||||||
|
if 'INTERFACE_TYPE' in d:
|
||||||
|
for opt in (
|
||||||
|
'MEMORY',
|
||||||
|
'MEMORY_DDR3',
|
||||||
|
'MEMORY_QDR',
|
||||||
|
'NETWORKING',
|
||||||
|
'OVERSAMPLE',
|
||||||
|
):
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'ISERDES.INTERFACE_TYPE.{}'.format(opt),
|
||||||
|
opt == verilog.unquote(d['INTERFACE_TYPE']))
|
||||||
|
|
||||||
|
if d['iddr_mux_config'] != 'none':
|
||||||
|
segmk.add_site_tag(site, 'IFF.ZINIT_Q1', not d['INIT_Q1'])
|
||||||
|
segmk.add_site_tag(site, 'IFF.ZINIT_Q2', not d['INIT_Q2'])
|
||||||
|
|
||||||
|
if 'INIT_Q3' in d:
|
||||||
|
segmk.add_site_tag(site, 'IFF.ZINIT_Q3', not d['INIT_Q3'])
|
||||||
|
segmk.add_site_tag(site, 'IFF.ZINIT_Q4', not d['INIT_Q4'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZSRVAL_Q1', not d['SRVAL_Q1'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZSRVAL_Q2', not d['SRVAL_Q2'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZSRVAL_Q3', not d['SRVAL_Q3'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZSRVAL_Q4', not d['SRVAL_Q4'])
|
||||||
|
|
||||||
|
if 'IS_CLK_INVERTED' in d:
|
||||||
|
if verilog.unquote(d['INTERFACE_TYPE']) == 'MEMORY_DDR3':
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLK', not d['IS_CLK_INVERTED'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLKB', not d['IS_CLKB_INVERTED'])
|
||||||
|
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLK_XOR',
|
||||||
|
d['IS_CLK_INVERTED'] ^ d['IS_CLKB_INVERTED'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLK_NXOR',
|
||||||
|
not (d['IS_CLK_INVERTED'] ^ d['IS_CLKB_INVERTED']))
|
||||||
|
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLK_OR', d['IS_CLK_INVERTED']
|
||||||
|
or d['IS_CLKB_INVERTED'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLK_NOR', not (
|
||||||
|
d['IS_CLK_INVERTED'] or d['IS_CLKB_INVERTED']))
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLK_AND', d['IS_CLK_INVERTED']
|
||||||
|
and d['IS_CLKB_INVERTED'])
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_CLK_NAND', not (
|
||||||
|
d['IS_CLK_INVERTED']
|
||||||
|
and d['IS_CLKB_INVERTED']))
|
||||||
|
|
||||||
|
if 'IS_OCLK_INVERTED' in d:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_OCLK', not d['IS_OCLK_INVERTED'])
|
||||||
|
|
||||||
|
if 'IS_C_INVERTED' in d:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.ZINV_C', not d['IS_C_INVERTED'])
|
||||||
|
|
||||||
|
segmk.add_site_tag(site, 'ZINV_D', not d['IS_D_INVERTED'])
|
||||||
|
|
||||||
|
if 'SRTYPE' in d:
|
||||||
|
for opt in ['ASYNC', 'SYNC']:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.SRTYPE.{}'.format(opt),
|
||||||
|
verilog.unquote(d['SRTYPE']) == opt)
|
||||||
|
|
||||||
|
if 'DDR_CLK_EDGE' in d:
|
||||||
|
for opt in ['OPPOSITE_EDGE', 'SAME_EDGE',
|
||||||
|
'SAME_EDGE_PIPELINED']:
|
||||||
|
segmk.add_site_tag(
|
||||||
|
site, 'IFF.DDR_CLK_EDGE.{}'.format(opt),
|
||||||
|
verilog.unquote(d['DDR_CLK_EDGE']) == opt)
|
||||||
|
|
||||||
|
ofb_used = False
|
||||||
|
if 'OFB_USED' in d and d['OFB_USED']:
|
||||||
|
ofb_used = True
|
||||||
|
|
||||||
|
if d['iddr_mux_config'] == 'direct':
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.0', 0)
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.1', 1)
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.2', 0)
|
||||||
|
|
||||||
|
if ofb_used:
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.1', 1)
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.0', 0)
|
||||||
|
else:
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.0', 1)
|
||||||
|
elif d['iddr_mux_config'] == 'idelay':
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.0', 1)
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.2', 0)
|
||||||
|
|
||||||
|
if ofb_used:
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.1', 1)
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.0', 0)
|
||||||
|
else:
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IFFMUX.0', 1)
|
||||||
|
elif d['iddr_mux_config'] == 'none':
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.0', 0)
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IFFDELMUXE3.2', 0)
|
||||||
|
else:
|
||||||
|
assert False, d['mux_config']
|
||||||
|
|
||||||
|
if d['mux_config'] == 'direct':
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.0', 0)
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.1', 1)
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.2', 0)
|
||||||
|
|
||||||
|
if ofb_used:
|
||||||
|
segmk.add_site_tag(site, 'IMUX.1', 1)
|
||||||
|
segmk.add_site_tag(site, 'IMUX.0', 0)
|
||||||
|
else:
|
||||||
|
segmk.add_site_tag(site, 'IMUX.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IMUX.0', 1)
|
||||||
|
elif d['mux_config'] == 'idelay':
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.0', 1)
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.2', 0)
|
||||||
|
|
||||||
|
if ofb_used:
|
||||||
|
segmk.add_site_tag(site, 'IMUX.1', 1)
|
||||||
|
segmk.add_site_tag(site, 'IMUX.0', 0)
|
||||||
|
else:
|
||||||
|
segmk.add_site_tag(site, 'IMUX.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IMUX.0', 1)
|
||||||
|
elif d['mux_config'] == 'none':
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.0', 0)
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.1', 0)
|
||||||
|
segmk.add_site_tag(site, 'IDELMUXE3.2', 0)
|
||||||
|
else:
|
||||||
|
assert False, d['mux_config']
|
||||||
|
|
||||||
|
segmk.compile()
|
||||||
|
segmk.write(allow_empty=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -19,6 +19,8 @@ proc load_pin_lines {} {
|
||||||
# IOB_X0Y129 do[0] output
|
# IOB_X0Y129 do[0] output
|
||||||
|
|
||||||
set fp [open "params.csv" r]
|
set fp [open "params.csv" r]
|
||||||
|
gets $fp line
|
||||||
|
|
||||||
set pin_lines {}
|
set pin_lines {}
|
||||||
for {gets $fp line} {$line != ""} {gets $fp line} {
|
for {gets $fp line} {$line != ""} {gets $fp line} {
|
||||||
lappend pin_lines [split $line ","]
|
lappend pin_lines [split $line ","]
|
||||||
|
|
@ -31,36 +33,46 @@ proc loc_pins {} {
|
||||||
set pin_lines [load_pin_lines]
|
set pin_lines [load_pin_lines]
|
||||||
set io_pin_sites [make_io_pin_sites]
|
set io_pin_sites [make_io_pin_sites]
|
||||||
|
|
||||||
set fp [open "design.csv" w]
|
|
||||||
puts $fp "port,site,tile,pin,val"
|
|
||||||
|
|
||||||
puts "Looping"
|
puts "Looping"
|
||||||
for {set idx 1} {$idx < [llength $pin_lines]} {incr idx} {
|
for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
|
||||||
set line [lindex $pin_lines $idx]
|
set line [lindex $pin_lines $idx]
|
||||||
puts "$line"
|
puts "$line"
|
||||||
|
|
||||||
set site_str [lindex $line 0]
|
set site_str [lindex $line 1]
|
||||||
set pin_str [lindex $line 1]
|
set pin_str [lindex $line 2]
|
||||||
set io [lindex $line 2]
|
set iostandard [lindex $line 3]
|
||||||
set cell_str [lindex $line 3]
|
set drive [lindex $line 4]
|
||||||
# Skip unused site
|
set slew [lindex $line 5]
|
||||||
if {"$pin_str" == ""} {
|
set pulltype [lindex $line 6]
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
# Have: site
|
# Have: site
|
||||||
# Want: pin for site
|
# Want: pin for site
|
||||||
|
|
||||||
set site [get_sites $site_str]
|
set site [get_sites $site_str]
|
||||||
set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
|
set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
|
||||||
|
# set port [get_ports -of_objects $site]
|
||||||
set port [get_ports $pin_str]
|
set port [get_ports $pin_str]
|
||||||
set tile [get_tiles -of_objects $site]
|
set tile [get_tiles -of_objects $site]
|
||||||
|
|
||||||
set pin [dict get $io_pin_sites $site]
|
set pin [dict get $io_pin_sites $site]
|
||||||
|
|
||||||
set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS33" $port
|
set props {}
|
||||||
|
#lappend props PACKAGE_PIN $pin
|
||||||
|
lappend props IOSTANDARD $iostandard
|
||||||
|
lappend props PULLTYPE $pulltype
|
||||||
|
|
||||||
puts $fp "$port,$site,$tile,$pin"
|
if {$drive != "None"} {
|
||||||
|
lappend props DRIVE $drive
|
||||||
|
}
|
||||||
|
|
||||||
|
if {$slew != "None"} {
|
||||||
|
lappend props SLEW $slew
|
||||||
|
}
|
||||||
|
|
||||||
|
puts $props
|
||||||
|
|
||||||
|
set_property -dict "$props" $port
|
||||||
}
|
}
|
||||||
close $fp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc run {} {
|
proc run {} {
|
||||||
|
|
@ -68,17 +80,14 @@ proc run {} {
|
||||||
read_verilog top.v
|
read_verilog top.v
|
||||||
synth_design -top top
|
synth_design -top top
|
||||||
|
|
||||||
# Mostly doesn't matter since IOB are special, but add anyway
|
|
||||||
create_pblock roi
|
|
||||||
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
|
|
||||||
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
|
|
||||||
|
|
||||||
loc_pins
|
loc_pins
|
||||||
|
|
||||||
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]
|
||||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||||
set_param tcl.collectionResultDisplayLimit 0
|
set_property IS_ENABLED 0 [get_drc_checks {REQP-79}]
|
||||||
|
|
||||||
|
write_checkpoint -force design_pre_place.dcp
|
||||||
|
|
||||||
place_design
|
place_design
|
||||||
route_design
|
route_design
|
||||||
|
|
@ -0,0 +1,442 @@
|
||||||
|
import json
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
random.seed(int(os.getenv("SEED"), 16))
|
||||||
|
from prjxray import util
|
||||||
|
from prjxray import lut_maker
|
||||||
|
from prjxray import verilog
|
||||||
|
from prjxray.db import Database
|
||||||
|
|
||||||
|
|
||||||
|
def gen_sites():
|
||||||
|
'''
|
||||||
|
IOB33S: main IOB of a diff pair
|
||||||
|
IOB33M: secondary IOB of a diff pair
|
||||||
|
IOB33: not a diff pair. Relatively rare (at least in ROI...2 of them?)
|
||||||
|
Focus on IOB33S to start
|
||||||
|
'''
|
||||||
|
db = Database(util.get_db_root())
|
||||||
|
grid = db.grid()
|
||||||
|
for tile_name in sorted(grid.tiles()):
|
||||||
|
loc = grid.loc_of_tilename(tile_name)
|
||||||
|
gridinfo = grid.gridinfo_at_loc(loc)
|
||||||
|
|
||||||
|
for site_name, site_type in gridinfo.sites.items():
|
||||||
|
if site_type in ['IOB33S', 'IOB33M']:
|
||||||
|
yield tile_name, site_name
|
||||||
|
|
||||||
|
|
||||||
|
def write_params(params):
|
||||||
|
pinstr = 'tile,site,pin,iostandard,drive,slew\n'
|
||||||
|
for vals in params:
|
||||||
|
pinstr += ','.join(map(str, vals)) + '\n'
|
||||||
|
|
||||||
|
open('params.csv', 'w').write(pinstr)
|
||||||
|
|
||||||
|
|
||||||
|
def use_iserdese2(p, luts, connects):
|
||||||
|
iobdelay = random.choice((
|
||||||
|
'NONE',
|
||||||
|
'BOTH',
|
||||||
|
'IBUF',
|
||||||
|
'IFD',
|
||||||
|
))
|
||||||
|
|
||||||
|
p['IOBDELAY'] = verilog.quote(iobdelay)
|
||||||
|
p['INIT_Q1'] = random.randint(0, 1)
|
||||||
|
p['INIT_Q2'] = random.randint(0, 1)
|
||||||
|
p['INIT_Q3'] = random.randint(0, 1)
|
||||||
|
p['INIT_Q4'] = random.randint(0, 1)
|
||||||
|
|
||||||
|
p['SRVAL_Q1'] = random.randint(0, 1)
|
||||||
|
p['SRVAL_Q2'] = random.randint(0, 1)
|
||||||
|
p['SRVAL_Q3'] = random.randint(0, 1)
|
||||||
|
p['SRVAL_Q4'] = random.randint(0, 1)
|
||||||
|
p['NUM_CE'] = random.randint(1, 2)
|
||||||
|
|
||||||
|
p['IS_CLK_INVERTED'] = random.randint(0, 1)
|
||||||
|
p['IS_CLKB_INVERTED'] = random.randint(0, 1)
|
||||||
|
p['IS_OCLK_INVERTED'] = random.randint(0, 1)
|
||||||
|
p['IS_D_INVERTED'] = random.randint(0, 1)
|
||||||
|
p['INTERFACE_TYPE'] = verilog.quote(
|
||||||
|
random.choice(
|
||||||
|
(
|
||||||
|
'MEMORY',
|
||||||
|
'MEMORY_DDR3',
|
||||||
|
'MEMORY_QDR',
|
||||||
|
'NETWORKING',
|
||||||
|
'OVERSAMPLE',
|
||||||
|
)))
|
||||||
|
p['DATA_RATE'] = verilog.quote(random.choice((
|
||||||
|
'SDR',
|
||||||
|
'DDR',
|
||||||
|
)))
|
||||||
|
if verilog.unquote(p['DATA_RATE']) == 'SDR':
|
||||||
|
data_widths = [2, 3, 4, 5, 6, 7, 8]
|
||||||
|
else:
|
||||||
|
data_widths = [4, 6, 8]
|
||||||
|
|
||||||
|
p['DATA_WIDTH'] = random.choice(data_widths)
|
||||||
|
p['SERDES_MODE'] = verilog.quote(random.choice(('MASTER', 'SLAVE')))
|
||||||
|
|
||||||
|
use_delay = iobdelay != 'NONE'
|
||||||
|
|
||||||
|
if iobdelay == 'NONE':
|
||||||
|
p['mux_config'] = 'direct'
|
||||||
|
p['iddr_mux_config'] = 'direct'
|
||||||
|
elif iobdelay == 'BOTH':
|
||||||
|
p['mux_config'] = 'idelay'
|
||||||
|
p['iddr_mux_config'] = 'idelay'
|
||||||
|
elif iobdelay == 'IBUF':
|
||||||
|
p['mux_config'] = 'idelay'
|
||||||
|
p['iddr_mux_config'] = 'direct'
|
||||||
|
elif iobdelay == 'IFD':
|
||||||
|
p['mux_config'] = 'direct'
|
||||||
|
p['iddr_mux_config'] = 'idelay'
|
||||||
|
|
||||||
|
p['OFB_USED'] = verilog.quote(random.choice(('TRUE', 'FALSE')))
|
||||||
|
p['DYN_CLKDIV_INV_EN'] = verilog.quote(random.choice(('TRUE', 'FALSE')))
|
||||||
|
p['DYN_CLK_INV_EN'] = verilog.quote(random.choice(('TRUE', 'FALSE')))
|
||||||
|
|
||||||
|
if use_delay:
|
||||||
|
print(
|
||||||
|
"""
|
||||||
|
wire idelay_{site};
|
||||||
|
|
||||||
|
(* KEEP, DONT_TOUCH, LOC = "{idelay_loc}" *)
|
||||||
|
IDELAYE2 #(
|
||||||
|
) idelay_site_{site} (
|
||||||
|
.IDATAIN({iwire}),
|
||||||
|
.DATAOUT(idelay_{site})
|
||||||
|
);""".format(**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
|
p['ddly_connection'] = '.DDLY(idelay_{site}),'.format(**p)
|
||||||
|
else:
|
||||||
|
p['ddly_connection'] = ''
|
||||||
|
|
||||||
|
if verilog.unquote(p['OFB_USED']) == 'TRUE':
|
||||||
|
p['ODATA_RATE'] = verilog.quote(random.choice((
|
||||||
|
'SDR',
|
||||||
|
'DDR',
|
||||||
|
)))
|
||||||
|
if verilog.unquote(p['ODATA_RATE']) == 'SDR':
|
||||||
|
data_widths = [2, 3, 4, 5, 6, 7, 8]
|
||||||
|
else:
|
||||||
|
data_widths = [4, 6, 8]
|
||||||
|
|
||||||
|
p['ODATA_WIDTH'] = random.choice(data_widths)
|
||||||
|
p['OSERDES_MODE'] = verilog.quote(random.choice(('MASTER', 'SLAVE')))
|
||||||
|
|
||||||
|
if p['ODATA_WIDTH'] == 4 and verilog.unquote(p['ODATA_RATE']) == 'DDR':
|
||||||
|
p['TRISTATE_WIDTH'] = 4
|
||||||
|
else:
|
||||||
|
p['TRISTATE_WIDTH'] = 1
|
||||||
|
|
||||||
|
print(
|
||||||
|
"""
|
||||||
|
wire tfb_{site};
|
||||||
|
wire ofb_{site};
|
||||||
|
|
||||||
|
(* KEEP, DONT_TOUCH, LOC = "{ologic_loc}" *)
|
||||||
|
OSERDESE2 #(
|
||||||
|
.SERDES_MODE({OSERDES_MODE}),
|
||||||
|
.DATA_RATE_TQ({ODATA_RATE}),
|
||||||
|
.DATA_RATE_OQ({ODATA_RATE}),
|
||||||
|
.DATA_WIDTH({ODATA_WIDTH}),
|
||||||
|
.TRISTATE_WIDTH({TRISTATE_WIDTH})
|
||||||
|
) oserdese2_{site} (
|
||||||
|
.CLK(0),
|
||||||
|
.CLKDIV(0),
|
||||||
|
.D1(0),
|
||||||
|
.TFB(tfb_{site}),
|
||||||
|
.OQ({owire}),
|
||||||
|
.TQ({twire}),
|
||||||
|
.OFB(ofb_{site})
|
||||||
|
);""".format(**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
|
p['ofb_connections'] = """
|
||||||
|
.OFB(ofb_{site}),
|
||||||
|
""".format(**p)
|
||||||
|
else:
|
||||||
|
p['ofb_connections'] = ''
|
||||||
|
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
(* KEEP, DONT_TOUCH, LOC = "{ilogic_loc}" *)
|
||||||
|
ISERDESE2 #(
|
||||||
|
.SERDES_MODE({SERDES_MODE}),
|
||||||
|
.INIT_Q1({INIT_Q1}),
|
||||||
|
.INIT_Q2({INIT_Q2}),
|
||||||
|
.INIT_Q3({INIT_Q3}),
|
||||||
|
.INIT_Q4({INIT_Q4}),
|
||||||
|
.SRVAL_Q1({SRVAL_Q1}),
|
||||||
|
.SRVAL_Q2({SRVAL_Q2}),
|
||||||
|
.SRVAL_Q3({SRVAL_Q3}),
|
||||||
|
.SRVAL_Q4({SRVAL_Q4}),
|
||||||
|
.DYN_CLKDIV_INV_EN({DYN_CLKDIV_INV_EN}),
|
||||||
|
.DYN_CLK_INV_EN({DYN_CLK_INV_EN}),
|
||||||
|
.INTERFACE_TYPE({INTERFACE_TYPE}),
|
||||||
|
.IS_CLK_INVERTED({IS_CLK_INVERTED}),
|
||||||
|
.IS_CLKB_INVERTED({IS_CLKB_INVERTED}),
|
||||||
|
.IS_OCLK_INVERTED({IS_OCLK_INVERTED}),
|
||||||
|
.IS_D_INVERTED({IS_D_INVERTED}),
|
||||||
|
.OFB_USED({OFB_USED}),
|
||||||
|
.NUM_CE({NUM_CE}),
|
||||||
|
.DATA_RATE({DATA_RATE}),
|
||||||
|
.IOBDELAY({IOBDELAY})
|
||||||
|
) iserdese2_{site} (
|
||||||
|
{ddly_connection}
|
||||||
|
{ofb_connections}
|
||||||
|
.D({iwire}),
|
||||||
|
.CLK({clknet}),
|
||||||
|
.CLKB({clkbnet}),
|
||||||
|
.OCLK({oclknet}),
|
||||||
|
.O({onet}),
|
||||||
|
.Q1({q1net}),
|
||||||
|
.CLKDIV(0)
|
||||||
|
);'''.format(
|
||||||
|
clknet=luts.get_next_output_net(),
|
||||||
|
clkbnet=luts.get_next_output_net(),
|
||||||
|
oclknet=luts.get_next_output_net(),
|
||||||
|
onet=luts.get_next_input_net(),
|
||||||
|
q1net=luts.get_next_input_net(),
|
||||||
|
shiftout1net=luts.get_next_input_net(),
|
||||||
|
shiftout2net=luts.get_next_input_net(),
|
||||||
|
**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
|
|
||||||
|
def use_direct_and_iddr(p, luts, connects):
|
||||||
|
p['mux_config'] = random.choice((
|
||||||
|
'direct',
|
||||||
|
'idelay',
|
||||||
|
'none',
|
||||||
|
))
|
||||||
|
|
||||||
|
p['iddr_mux_config'] = random.choice((
|
||||||
|
'direct',
|
||||||
|
'idelay',
|
||||||
|
'none',
|
||||||
|
))
|
||||||
|
|
||||||
|
if p['iddr_mux_config'] != 'none':
|
||||||
|
p['INIT_Q1'] = random.randint(0, 1)
|
||||||
|
p['INIT_Q2'] = random.randint(0, 1)
|
||||||
|
p['IS_C_INVERTED'] = random.randint(0, 1)
|
||||||
|
p['IS_D_INVERTED'] = random.randint(0, 1)
|
||||||
|
p['SRTYPE'] = verilog.quote(random.choice(('SYNC', 'ASYNC')))
|
||||||
|
p['DDR_CLK_EDGE'] = verilog.quote(
|
||||||
|
random.choice(
|
||||||
|
(
|
||||||
|
'OPPOSITE_EDGE',
|
||||||
|
'SAME_EDGE',
|
||||||
|
'SAME_EDGE_PIPELINED',
|
||||||
|
)))
|
||||||
|
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
(* KEEP, DONT_TOUCH, LOC = "{ilogic_loc}" *)
|
||||||
|
IDDR #(
|
||||||
|
.IS_D_INVERTED({IS_D_INVERTED}),
|
||||||
|
.IS_C_INVERTED({IS_C_INVERTED}),
|
||||||
|
.INIT_Q1({INIT_Q1}),
|
||||||
|
.INIT_Q2({INIT_Q2}),
|
||||||
|
.SRTYPE({SRTYPE}),
|
||||||
|
.DDR_CLK_EDGE({DDR_CLK_EDGE})
|
||||||
|
) iddr_{site} (
|
||||||
|
.C({cnet}),
|
||||||
|
.D(iddr_d_{site}),
|
||||||
|
.Q1({q1}),
|
||||||
|
.Q2({q2})
|
||||||
|
);
|
||||||
|
'''.format(
|
||||||
|
cnet=luts.get_next_output_net(),
|
||||||
|
q1=luts.get_next_input_net(),
|
||||||
|
q2=luts.get_next_input_net(),
|
||||||
|
**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
|
if p['iddr_mux_config'] == 'idelay' or p['mux_config'] == 'idelay' or p[
|
||||||
|
'iddr_mux_config'] == 'tristate_feedback':
|
||||||
|
print(
|
||||||
|
"""
|
||||||
|
wire idelay_{site};
|
||||||
|
|
||||||
|
(* KEEP, DONT_TOUCH, LOC = "{idelay_loc}" *)
|
||||||
|
IDELAYE2 #(
|
||||||
|
) idelay_site_{site} (
|
||||||
|
.IDATAIN({iwire}),
|
||||||
|
.DATAOUT(idelay_{site})
|
||||||
|
);""".format(**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
|
print(
|
||||||
|
"""
|
||||||
|
assign {owire} = {onet};
|
||||||
|
assign {twire} = {tnet};
|
||||||
|
""".format(
|
||||||
|
onet=luts.get_next_output_net(),
|
||||||
|
tnet=luts.get_next_output_net(),
|
||||||
|
**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
|
if p['iddr_mux_config'] == 'direct':
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
assign iddr_d_{site} = {iwire};'''.format(**p, ),
|
||||||
|
file=connects)
|
||||||
|
elif p['iddr_mux_config'] == 'idelay':
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
assign iddr_d_{site} = idelay_{site};'''.format(**p, ),
|
||||||
|
file=connects)
|
||||||
|
elif p['iddr_mux_config'] == 'tristate_feedback':
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
assign iddr_d_{site} = tfb_{site} ? ofb_{site} : idelay_{site};'''.format(
|
||||||
|
**p, ),
|
||||||
|
file=connects)
|
||||||
|
elif p['iddr_mux_config'] == 'none':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
assert False, p['mux_config']
|
||||||
|
|
||||||
|
if p['mux_config'] == 'direct':
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
assign {net} = {iwire};'''.format(
|
||||||
|
net=luts.get_next_input_net(),
|
||||||
|
**p,
|
||||||
|
),
|
||||||
|
file=connects)
|
||||||
|
elif p['mux_config'] == 'idelay':
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
assign {net} = idelay_{site};'''.format(
|
||||||
|
net=luts.get_next_input_net(),
|
||||||
|
**p,
|
||||||
|
),
|
||||||
|
file=connects)
|
||||||
|
elif p['mux_config'] == 'none':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
assert False, p['mux_config']
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
iostandards = [
|
||||||
|
'LVCMOS12', 'LVCMOS15', 'LVCMOS18', 'LVCMOS25', 'LVCMOS33', 'LVTTL'
|
||||||
|
]
|
||||||
|
iostandard = random.choice(iostandards)
|
||||||
|
|
||||||
|
if iostandard in ['LVTTL', 'LVCMOS18']:
|
||||||
|
drives = [4, 8, 12, 16, 24]
|
||||||
|
elif iostandard == 'LVCMOS12':
|
||||||
|
drives = [4, 8, 12]
|
||||||
|
else:
|
||||||
|
drives = [4, 8, 12, 16]
|
||||||
|
|
||||||
|
slews = ['FAST', 'SLOW']
|
||||||
|
pulls = ["NONE", "KEEPER", "PULLDOWN", "PULLUP"]
|
||||||
|
|
||||||
|
luts = lut_maker.LutMaker()
|
||||||
|
|
||||||
|
connects = io.StringIO()
|
||||||
|
|
||||||
|
tile_params = []
|
||||||
|
params = []
|
||||||
|
for idx, (tile, site) in enumerate(gen_sites()):
|
||||||
|
if idx == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
p = {}
|
||||||
|
p['tile'] = tile
|
||||||
|
p['site'] = site
|
||||||
|
p['ilogic_loc'] = site.replace('IOB', 'ILOGIC')
|
||||||
|
p['ologic_loc'] = site.replace('IOB', 'OLOGIC')
|
||||||
|
p['idelay_loc'] = site.replace('IOB', 'IDELAY')
|
||||||
|
p['IOSTANDARD'] = verilog.quote(iostandard)
|
||||||
|
p['PULLTYPE'] = verilog.quote(random.choice(pulls))
|
||||||
|
p['DRIVE'] = random.choice(drives)
|
||||||
|
p['SLEW'] = verilog.quote(random.choice(slews))
|
||||||
|
|
||||||
|
p['pad_wire'] = 'dio[{}]'.format(idx - 1)
|
||||||
|
p['owire'] = 'do_buf[{}]'.format(idx - 1)
|
||||||
|
p['iwire'] = 'di_buf[{}]'.format(idx - 1)
|
||||||
|
p['twire'] = 't[{}]'.format(idx - 1)
|
||||||
|
|
||||||
|
params.append(p)
|
||||||
|
tile_params.append(
|
||||||
|
(
|
||||||
|
tile, site, p['pad_wire'], iostandard, p['DRIVE'],
|
||||||
|
verilog.unquote(p['SLEW']) if p['SLEW'] else None,
|
||||||
|
verilog.unquote(p['PULLTYPE'])))
|
||||||
|
|
||||||
|
write_params(tile_params)
|
||||||
|
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
`define N_DI {n_di}
|
||||||
|
|
||||||
|
module top(input clk, inout wire [`N_DI-1:0] dio);
|
||||||
|
wire [`N_DI-1:0] di_buf;
|
||||||
|
wire [`N_DI-1:0] do_buf;
|
||||||
|
wire [`N_DI-1:0] t;
|
||||||
|
'''.format(n_di=idx))
|
||||||
|
|
||||||
|
# Always output a LUT6 to make placer happy.
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
LUT6 dummy_lut();
|
||||||
|
''')
|
||||||
|
|
||||||
|
any_idelay = False
|
||||||
|
|
||||||
|
for p in params:
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
wire iddr_d_{site};
|
||||||
|
|
||||||
|
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||||
|
IOBUF #(
|
||||||
|
.IOSTANDARD({IOSTANDARD})
|
||||||
|
) ibuf_{site} (
|
||||||
|
.IO({pad_wire}),
|
||||||
|
.I({owire}),
|
||||||
|
.O({iwire}),
|
||||||
|
.T({twire})
|
||||||
|
);
|
||||||
|
'''.format(**p),
|
||||||
|
file=connects)
|
||||||
|
|
||||||
|
p['use_iserdese2'] = random.randint(0, 1)
|
||||||
|
if p['use_iserdese2']:
|
||||||
|
use_iserdese2(p, luts, connects)
|
||||||
|
else:
|
||||||
|
use_direct_and_iddr(p, luts, connects)
|
||||||
|
|
||||||
|
if p['iddr_mux_config'] == 'idelay' or p['mux_config'] == 'idelay':
|
||||||
|
any_idelay = True
|
||||||
|
|
||||||
|
if any_idelay:
|
||||||
|
print("""
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
IDELAYCTRL();""")
|
||||||
|
|
||||||
|
for l in luts.create_wires_and_luts():
|
||||||
|
print(l)
|
||||||
|
|
||||||
|
print(connects.getvalue())
|
||||||
|
|
||||||
|
print("endmodule")
|
||||||
|
|
||||||
|
with open('params.jl', 'w') as f:
|
||||||
|
json.dump(params, f, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
|
|
@ -73,6 +73,8 @@ $(eval $(call fuzzer,026-bram-data,005-tilegrid))
|
||||||
$(eval $(call fuzzer,027-bram36-config,005-tilegrid))
|
$(eval $(call fuzzer,027-bram36-config,005-tilegrid))
|
||||||
$(eval $(call fuzzer,028-fifo-config,005-tilegrid))
|
$(eval $(call fuzzer,028-fifo-config,005-tilegrid))
|
||||||
$(eval $(call fuzzer,029-bram-fifo-config,005-tilegrid))
|
$(eval $(call fuzzer,029-bram-fifo-config,005-tilegrid))
|
||||||
|
$(eval $(call fuzzer,030-iob,005-tilegrid))
|
||||||
|
$(eval $(call fuzzer,035-iob-ilogic,005-tilegrid))
|
||||||
$(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid))
|
$(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid))
|
||||||
$(eval $(call fuzzer,041-clk-hrow-pips,005-tilegrid))
|
$(eval $(call fuzzer,041-clk-hrow-pips,005-tilegrid))
|
||||||
# 042 fuzzer is unstable, issue #657
|
# 042 fuzzer is unstable, issue #657
|
||||||
|
|
|
||||||
|
|
@ -336,9 +336,13 @@ class Segmaker:
|
||||||
-CLBLM_L => CLB
|
-CLBLM_L => CLB
|
||||||
-CENTER_INTER_R => CENTER_INTER
|
-CENTER_INTER_R => CENTER_INTER
|
||||||
-CLK_HROW_TOP_R => CLK_HROW
|
-CLK_HROW_TOP_R => CLK_HROW
|
||||||
|
-LIOB33 => IOB33
|
||||||
'''
|
'''
|
||||||
tile_type_norm = re.sub("(_TOP|_BOT|LL|LM)?_[LR]$", "", tile_type)
|
tile_type_norm = re.sub("(_TOP|_BOT|LL|LM)?_[LR]$", "", tile_type)
|
||||||
|
|
||||||
|
if tile_type_norm in ['LIOB33', 'RIOB33']:
|
||||||
|
tile_type_norm = 'IOB33'
|
||||||
|
|
||||||
# ignore dummy tiles (ex: VBRK)
|
# ignore dummy tiles (ex: VBRK)
|
||||||
if len(tiledata['bits']) == 0:
|
if len(tiledata['bits']) == 0:
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,10 @@ case "$1" in
|
||||||
cp "$2" "$tmp1" ;;
|
cp "$2" "$tmp1" ;;
|
||||||
|
|
||||||
liob33)
|
liob33)
|
||||||
cp "$2" "$tmp1" ;;
|
sed < "$2" > "$tmp1" -e 's/^IOB33\./LIOB33./' ;;
|
||||||
|
|
||||||
|
riob33)
|
||||||
|
sed < "$2" > "$tmp1" -e 's/^IOB33\./RIOB33./' ;;
|
||||||
|
|
||||||
mask_*)
|
mask_*)
|
||||||
db=$XRAY_DATABASE_DIR/$XRAY_DATABASE/$1.db
|
db=$XRAY_DATABASE_DIR/$XRAY_DATABASE/$1.db
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue