Merge pull request #934 from antmicro/ioi3-pips

IOI3_INTER pips fuzzer
This commit is contained in:
litghost 2019-07-26 19:25:38 -07:00 committed by GitHub
commit 9d0065a768
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 623 additions and 4 deletions

View File

@ -39,6 +39,10 @@ DB_SIMPLE=\
$(addsuffix _r, $(DB_SIMPLE_LR) $(DB_SIMPLE_R)) \
segbits_cmt_top_l_upper_t \
segbits_cmt_top_r_upper_t \
segbits_lioi3 \
segbits_rioi3 \
segbits_liob33 \
segbits_riob33
BLOCK_RAM_EXTRA_FOR=\
mask_bram \

View File

@ -0,0 +1,50 @@
export FUZDIR=$(shell pwd)
PIP_TYPE?=ioi3
PIPLIST_TCL=$(FUZDIR)/ioi3_pip_list.tcl
TODO_RE="[LR]IOI3\.(IOI_([IO]LOGIC[01]_CLK(DIV|B)?)|(IOI_OCLK_[01]))\..*"
EXCLUDE_RE=".*\..*\.(?=IOI_((PHASER)|(OCLK)|(IMUX22_1))).*"
MAKETODO_FLAGS=--pip-type ${PIP_TYPE} --seg-type $(PIP_TYPE) --re $(TODO_RE) --sides "xr,xl" --exclude-re $(EXCLUDE_RE)
N = 40
A_PIPLIST=lioi3.txt
SEGMATCH_FLAGS=-c -1 -m 20 -M 50
SPECIMENS_DEPS=build/cmt_regions.csv
include ../pip_loop.mk
build/segbits_ioi3_x.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_ioi3_x.rdb \
$(shell find build -name segdata_lioi3*.txt) $(shell find build -name segdata_rioi3*.txt)
RDBS = build/segbits_ioi3_x.rdb
database: ${RDBS}
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
--seg-fn-in build/segbits_ioi3_x.rdb \
--seg-fn-out build/segbits_ioi3_x.db
# Keep a copy to track iter progress
cp build/segbits_ioi3_x.rdb build/$(ITER)/segbits_ioi3_x.rdb
cp build/segbits_ioi3_x.db build/$(ITER)/segbits_ioi3_x.db
# Clobber existing .db to eliminate potential conflicts
cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} lioi3 build/segbits_ioi3_x.db
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} rioi3 build/segbits_ioi3_x.db
build/cmt_regions.csv: output_cmt.tcl
mkdir -p build
cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl
pushdb: database
${XRAY_MERGEDB} lioi3 build/segbits_ioi3_x.db
${XRAY_MERGEDB} rioi3 build/segbits_ioi3_x.db
${XRAY_MERGEDB} lioi3_tbytesrc build/segbits_ioi3_x.db
${XRAY_MERGEDB} rioi3_tbytesrc build/segbits_ioi3_x.db
${XRAY_MERGEDB} lioi3_tbyteterm build/segbits_ioi3_x.db
${XRAY_MERGEDB} rioi3_tbyteterm build/segbits_ioi3_x.db
.PHONY: database pushdb

View File

View File

@ -0,0 +1,104 @@
#!/usr/bin/env python3
from prjxray.segmaker import Segmaker
import os, re
import os.path
def bitfilter(frame, word):
if frame < 28:
return False
return True
def main():
segmk = Segmaker("design.bits")
tiledata = {}
pipdata = {}
ignpip = set()
with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
'ioi3', 'lioi3.txt')) as f:
for l in f:
tile_type, dst, src = l.strip().split('.')
if tile_type not in pipdata:
pipdata[tile_type] = []
pipdata[tile_type].append((src, dst))
with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
'ioi3', 'rioi3.txt')) as f:
for l in f:
tile_type, dst, src = l.strip().split('.')
if tile_type not in pipdata:
pipdata[tile_type] = []
pipdata[tile_type].append((src, dst))
print("Loading tags from design.txt.")
with open("design.txt", "r") as f:
for line in f:
tile, pip, src, dst, pnum, pdir = line.split()
if not tile.startswith('LIOI3') and not tile.startswith('RIOI3'):
continue
log = open("log.txt", "a")
print(line, file=log)
pip_prefix, _ = pip.split(".")
tile_from_pip, tile_type = pip_prefix.split('/')
_, src = src.split("/")
_, dst = dst.split("/")
pnum = int(pnum)
pdir = int(pdir)
if tile not in tiledata:
tiledata[tile] = {
"type": tile_type,
"pips": set(),
"srcs": set(),
"dsts": set(),
}
tiledata[tile]["pips"].add((src, dst))
tiledata[tile]["srcs"].add(src)
tiledata[tile]["dsts"].add(dst)
if pdir == 0:
tiledata[tile]["srcs"].add(dst)
tiledata[tile]["dsts"].add(src)
if pnum == 1 or pdir == 0:
print("Ignoring pip: {}".format(pip), file=log)
ignpip.add((src, dst))
for tile, pips_srcs_dsts in tiledata.items():
tile_type = pips_srcs_dsts["type"]
if tile_type.startswith('LIOI3'):
tile_type = 'LIOI3'
elif tile_type.startswith('RIOI3'):
tile_type = 'RIOI3'
pips = pips_srcs_dsts["pips"]
for src, dst in pipdata[tile_type]:
if (src, dst) in ignpip:
pass
if re.match(r'.*PHASER.*', src) or re.match(r'.*CLKDIV[PFB].*',
dst):
pass
elif (src, dst) in tiledata[tile]["pips"]:
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 1)
elif dst not in tiledata[tile]["dsts"]:
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0)
internal_feedback = False
segmk.compile(bitfilter=bitfilter)
segmk.write()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,55 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property IS_ENABLED 0 [get_drc_checks {AVAL-74}]
set_property IS_ENABLED 0 [get_drc_checks {PDRC-26}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-4}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-5}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-13}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-98}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-99}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-115}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-144}]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
place_design
write_checkpoint -force design_before_route.dcp
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
write_pip_txtdata design.txt
}
run

View File

@ -0,0 +1,39 @@
proc print_tile_pips {tile_type filename} {
set fp [open $filename w]
set pips [dict create]
foreach tile [get_tiles -filter "TYPE == $tile_type"] {
puts "Dumping PIPs for tile $tile ($tile_type) to $filename."
foreach pip [lsort [get_pips -of_objects $tile]] {
set src [get_wires -uphill -of_objects $pip]
set dst [get_wires -downhill -of_objects $pip]
# Skip pips with disconnected nodes
set src_node [get_nodes -of_objects $src]
if { $src_node == {} } {
continue
}
set dst_node [get_nodes -of_objects $src]
if { $dst_node == {} } {
continue
}
if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1} {
set pip_string "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
if ![dict exists $pips $pip_string] {
puts $fp $pip_string
dict set pips $pip_string 1
}
}
}
}
close $fp
}
create_project -force -part $::env(XRAY_PART) design design
set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
print_tile_pips LIOI3 lioi3.txt
print_tile_pips RIOI3 rioi3.txt

View File

@ -0,0 +1,11 @@
create_project -force -part $::env(XRAY_PART) design design
set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
set fp [open "cmt_regions.csv" "w"]
foreach site_type {MMCME2_ADV BUFHCE BUFR BUFMRCE BUFIO ILOGICE3 OLOGICE3 IDELAYE2 IDELAYCTRL PLLE2_ADV} {
foreach site [get_sites -filter "SITE_TYPE == $site_type"] {
puts $fp "$site,[get_property CLOCK_REGION $site]"
}
}
close $fp

345
fuzzers/037-iob-pips/top.py Normal file
View File

@ -0,0 +1,345 @@
import os
import random
import math
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray import verilog
from prjxray import lut_maker
from prjxray.db import Database
NOT_INCLUDED_TILES = ['LIOI3_SING', 'RIOI3_SING']
SITE_TYPES = ['OLOGICE3', 'ILOGICE3']
def read_site_to_cmt():
""" Yields clock sources and which CMT they route within. """
with open(os.path.join(os.getenv('FUZDIR'), 'build',
'cmt_regions.csv')) as f:
for l in f:
site, cmt = l.strip().split(',')
yield (site, cmt)
def gen_sites():
''' Return dict of ISERDES/OSERDES locations. '''
db = Database(util.get_db_root())
grid = db.grid()
xy_fun = util.create_xy_fun('\S+')
tiles = grid.tiles()
for tile_name in sorted(tiles):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
tile_type = gridinfo.tile_type
tile = {'tile': tile_name, 'tile_type': tile_type, 'ioi_sites': {}}
for site_name, site_type in gridinfo.sites.items():
if site_type in SITE_TYPES:
xy = xy_fun(site_name)
if xy not in tile['ioi_sites']:
tile['ioi_sites'][xy] = {}
tile['ioi_sites'][xy][site_type] = site_name
yield tile
class ClockSources(object):
def __init__(self):
self.site_to_cmt = dict(read_site_to_cmt())
self.leaf_gclks = {}
self.ioclks = {}
self.rclks = {}
self.selected_leaf_gclks = {}
self.lut_maker = lut_maker.LutMaker()
for cmt in set(self.site_to_cmt.values()):
self.leaf_gclks[cmt] = []
self.ioclks[cmt] = []
self.rclks[cmt] = []
def init_clocks(self):
""" Initialize all IOI clock sources. """
for site, cmt in self.site_to_cmt.items():
clk = 'clk_' + site
if 'BUFHCE' in site:
print(
"""
wire {clk};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
BUFH bufh_{site}(
.O({clk})
);
""".format(
clk=clk,
site=site,
))
self.leaf_gclks[cmt].append(clk)
if 'BUFIO' in site:
print(
"""
wire {clk};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
BUFIO bufio_{site}(
.O({clk})
);
""".format(
clk=clk,
site=site,
))
self.ioclks[cmt].append(clk)
if 'BUFR' in site:
print(
"""
wire {clk};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
BUFR bufr_{site}(
.O({clk})
);
""".format(
clk=clk,
site=site,
))
self.rclks[cmt].append(clk)
# Choose 6 leaf_gclks to be used in each CMT.
for cmt in self.leaf_gclks:
self.selected_leaf_gclks[cmt] = random.sample(
self.leaf_gclks[cmt], 6)
def get_clock(
self,
site,
allow_ioclks,
allow_rclks,
allow_fabric=True,
allow_empty=True):
cmt = self.site_to_cmt[site]
choices = []
if allow_fabric:
choices.append('lut')
if allow_empty:
choices.append('')
choices.extend(self.selected_leaf_gclks[cmt])
if allow_ioclks:
choices.extend(self.ioclks[cmt])
if allow_rclks:
choices.extend(self.rclks[cmt])
clock = random.choice(choices)
is_lut = False
if clock == "lut":
clock = self.lut_maker.get_next_output_net()
is_lut = True
return clock, is_lut
def add_port(ports, port, signal):
ports.append('.{}({})'.format(port, signal))
def run():
print("module top();")
clocks = ClockSources()
clocks.init_clocks()
"""
ISERDESE2 clock sources:
CLK/CLKB:
- Allows LEAF_GCLK, IOCLKS, RCLKS and fabric
- Dedicated pips
CLKDIV:
- No dedicated pips, uses fabric clock in.
CLKDIVP:
- Has pips, MIG only, PHASER or fabric.
OCLK/OCLKB:
- Allows LEAF_GCLK, IOCLKS, RCLKS and fabric
- Must match OSERDESE2:CLK/CLKB
OSERDESE2 clock sources:
CLKDIV/CLKDIVB:
- Allows LEAF_GCLK and RCLKS and fabric
- Dedicated pips
CLKDIVF/CLKDIVFB:
- Allows LEAF_GCLK and RCLKS and fabric
- No explicit port, follows CLKDIV/CLKDIVB?
"""
output = []
for tile in gen_sites():
if tile['tile_type'] in NOT_INCLUDED_TILES:
continue
for xy in tile['ioi_sites']:
ilogic_site_type = random.choice([None, 'ISERDESE2', 'IDDR'])
use_oserdes = random.randint(0, 1)
ilogic_site = tile['ioi_sites'][xy]['ILOGICE3']
ologic_site = tile['ioi_sites'][xy]['OLOGICE3']
if use_oserdes:
oclk, _ = clocks.get_clock(
ologic_site, allow_ioclks=True, allow_rclks=True)
oclkb = oclk
else:
oclk, is_lut = clocks.get_clock(
ilogic_site, allow_ioclks=True, allow_rclks=True)
if random.randint(0, 1):
oclkb = oclk
else:
oclkb, _ = clocks.get_clock(
ilogic_site,
allow_ioclks=True,
allow_rclks=True,
allow_fabric=not is_lut)
DATA_RATE = random.choice(['DDR', 'SDR'])
clk, is_lut = clocks.get_clock(
ilogic_site,
allow_ioclks=True,
allow_rclks=True,
allow_empty=DATA_RATE == 'SDR')
if False:
clkb = clk
else:
clkb = clk
while clkb == clk:
clkb, _ = clocks.get_clock(
ilogic_site,
allow_ioclks=True,
allow_rclks=True,
allow_empty=False)
if ilogic_site_type is None:
pass
elif ilogic_site_type == 'ISERDESE2':
INTERFACE_TYPE = random.choice(
[
'MEMORY',
'MEMORY_DDR3',
'MEMORY_QDR',
'NETWORKING',
'OVERSAMPLE',
])
ports = []
add_port(ports, 'CLK', clk)
add_port(ports, 'CLKB', clkb)
add_port(ports, 'OCLK', oclk)
add_port(ports, 'OCLKB', oclkb)
output.append(
"""
(* KEEP, DONT_TOUCH, LOC="{site}" *)
ISERDESE2 #(
.DATA_RATE({DATA_RATE}),
.INTERFACE_TYPE({INTERFACE_TYPE}),
.IS_CLK_INVERTED({IS_CLK_INVERTED}),
.IS_CLKB_INVERTED({IS_CLKB_INVERTED}),
.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})
) iserdes_{site}(
{ports});""".format(
site=ilogic_site,
ports=',\n'.join(ports),
DATA_RATE=verilog.quote(DATA_RATE),
INTERFACE_TYPE=verilog.quote(INTERFACE_TYPE),
IS_CLK_INVERTED=random.randint(0, 1),
IS_CLKB_INVERTED=random.randint(0, 1),
INIT_Q1=random.randint(0, 1),
INIT_Q2=random.randint(0, 1),
INIT_Q3=random.randint(0, 1),
INIT_Q4=random.randint(0, 1),
SRVAL_Q1=random.randint(0, 1),
SRVAL_Q2=random.randint(0, 1),
SRVAL_Q3=random.randint(0, 1),
SRVAL_Q4=random.randint(0, 1),
))
elif ilogic_site_type == 'IDDR':
ports = []
add_port(ports, 'C', clk)
add_port(ports, 'CB', clkb)
output.append(
"""
(* KEEP, DONT_TOUCH, LOC="{site}" *)
IDDR_2CLK #(
.INIT_Q1({INIT_Q1}),
.INIT_Q2({INIT_Q2}),
.SRTYPE({SRTYPE})
) iserdes_{site}(
{ports});""".format(
site=ilogic_site,
ports=',\n'.join(ports),
INIT_Q1=random.randint(0, 1),
INIT_Q2=random.randint(0, 1),
SRTYPE=verilog.quote(random.choice(['ASYNC', 'SYNC'])),
))
else:
assert False, ilogic_site_type
if use_oserdes:
ports = []
add_port(
ports, 'CLKDIV',
clocks.get_clock(
ologic_site,
allow_ioclks=False,
allow_rclks=True,
)[0])
add_port(ports, 'CLK', oclk)
output.append(
"""
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
OSERDESE2 #(
.DATA_RATE_OQ("SDR"),
.DATA_RATE_TQ("SDR")
) oserdes_{site} (
{ports});""".format(
site=ologic_site,
ports=',\n'.join(ports),
))
for s in clocks.lut_maker.create_wires_and_luts():
print(s)
for s in output:
print(s)
print("endmodule")
if __name__ == '__main__':
run()

View File

@ -88,6 +88,7 @@ $(eval $(call fuzzer,034-cmt-pll-pips,005-tilegrid))
$(eval $(call fuzzer,035-iob-ilogic,005-tilegrid))
$(eval $(call fuzzer,035a-iob-idelay,005-tilegrid))
$(eval $(call fuzzer,036-iob-ologic,005-tilegrid))
$(eval $(call fuzzer,037-iob-pips,005-tilegrid))
$(eval $(call fuzzer,038-cfg,005-tilegrid))
$(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid))
$(eval $(call fuzzer,041-clk-hrow-pips,005-tilegrid))

View File

@ -209,12 +209,22 @@ def run(
if side == "r" and not r:
continue
if side != "":
side = "_" + side
if side == "xl":
segfile = "l{}".format(seg_type)
pipfile = "l{}".format(pip_type)
elif side == "xr":
segfile = "r{}".format(seg_type)
pipfile = "r{}".format(pip_type)
elif side == "l" or side == "r":
segfile = "{}_{}".format(seg_type, side)
pipfile = "{}_{}".format(pip_type, side)
else:
segfile = "{}".format(seg_type)
pipfile = "{}".format(pip_type)
maketodo(
"%s/%s%s.txt" % (pip_dir, pip_type, side),
"%s/segbits_%s%s.db" % (db_dir, seg_type, side),
"%s/%s.txt" % (pip_dir, pipfile),
"%s/segbits_%s.db" % (db_dir, segfile),
intre,
exclude_re=exclude_re,
balance_wire_re=balance_wire_re,