mirror of https://github.com/openXC7/prjxray.git
Merge pull request #926 from litghost/add_pll_interconnect_fuzzer
Add PLL fuzzer
This commit is contained in:
commit
f400565f71
|
|
@ -36,7 +36,9 @@ DB_SIMPLE_L=$(addprefix segbits_,$(SEGBITS_L))
|
|||
DB_SIMPLE_R=$(addprefix segbits_,$(SEGBITS_R))
|
||||
DB_SIMPLE=\
|
||||
$(addsuffix _l, $(DB_SIMPLE_LR) $(DB_SIMPLE_L)) \
|
||||
$(addsuffix _r, $(DB_SIMPLE_LR) $(DB_SIMPLE_R))
|
||||
$(addsuffix _r, $(DB_SIMPLE_LR) $(DB_SIMPLE_R)) \
|
||||
segbits_cmt_top_l_upper_t \
|
||||
segbits_cmt_top_r_upper_t \
|
||||
|
||||
BLOCK_RAM_EXTRA_FOR=\
|
||||
mask_bram \
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ TILEGRID_TDB_DEPENDENCIES += monitor_int/build/segbits_tilegrid.tdb
|
|||
TILEGRID_TDB_DEPENDENCIES += clk_hrow/build/segbits_tilegrid.tdb
|
||||
TILEGRID_TDB_DEPENDENCIES += clk_bufg/build/segbits_tilegrid.tdb
|
||||
TILEGRID_TDB_DEPENDENCIES += hclk_cmt/build/segbits_tilegrid.tdb
|
||||
TILEGRID_TDB_DEPENDENCIES += pll/build/segbits_tilegrid.tdb
|
||||
TILEGRID_TDB_DEPENDENCIES += hclk_ioi/build/segbits_tilegrid.tdb
|
||||
GENERATE_FULL_ARGS=
|
||||
|
||||
|
|
@ -26,7 +27,6 @@ ifeq (${XRAY_DATABASE}, zynq7)
|
|||
TILEGRID_TDB_DEPENDENCIES += ps7_int/build/segbits_tilegrid.tdb
|
||||
else
|
||||
# Artix7/Kintex7 only
|
||||
TILEGRID_TDB_DEPENDENCIES += pll/build/segbits_tilegrid.tdb
|
||||
TILEGRID_TDB_DEPENDENCIES += mmcm/build/segbits_tilegrid.tdb
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ def run(fn_in, fn_out, verbose=False):
|
|||
("iob/build/segbits_tilegrid.tdb", 42, 4),
|
||||
("ioi/build/segbits_tilegrid.tdb", 42, 4),
|
||||
("mmcm/build/segbits_tilegrid.tdb", 30, 101),
|
||||
("pll/build/segbits_tilegrid.tdb", 30, 101),
|
||||
("pll/build/segbits_tilegrid.tdb", 30, 26),
|
||||
("monitor/build/segbits_tilegrid.tdb", 30, 101),
|
||||
("bram/build/segbits_tilegrid.tdb", 28, 10),
|
||||
("bram_block/build/segbits_tilegrid.tdb", 128, 10),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
N ?= 5
|
||||
GENERATE_ARGS?="--oneval 1 --design params.csv --dframe 1C --dword 98"
|
||||
GENERATE_ARGS?="--oneval 1 --design params.csv --dframe 1C --dword 23"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
|
|
|||
|
|
@ -1,12 +1,23 @@
|
|||
# read/write width is relatively slow to resolve
|
||||
# Even slower with multi bit masks...
|
||||
N := 8
|
||||
N := 50
|
||||
include ../fuzzer.mk
|
||||
|
||||
database: $(SPECIMENS_OK)
|
||||
database: build/segbits_cmt_top_upper_t.db
|
||||
|
||||
pushdb:
|
||||
echo "FIXME" && false
|
||||
build/segbits_cmt_top_upper_t.rdb: $(SPECIMENS_OK)
|
||||
${XRAY_SEGMATCH} -c 150 -o build/segbits_cmt_top_upper_t.rdb \
|
||||
$(shell find build -name "segdata_cmt_top_*_upper_t.txt")
|
||||
|
||||
build/segbits_cmt_top_upper_t.db: build/segbits_cmt_top_upper_t.rdb write_pll_reg.py
|
||||
python3 write_pll_reg.py \
|
||||
--seg_in build/segbits_cmt_top_upper_t.rdb \
|
||||
> build/segbits_cmt_top_upper_t.rdb2
|
||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
|
||||
--seg-fn-in build/segbits_cmt_top_upper_t.rdb2 \
|
||||
--seg-fn-out build/segbits_cmt_top_upper_t.db
|
||||
|
||||
pushdb: database
|
||||
${XRAY_MERGEDB} cmt_top_r_upper_t build/segbits_cmt_top_upper_t.db
|
||||
${XRAY_MERGEDB} cmt_top_l_upper_t build/segbits_cmt_top_upper_t.db
|
||||
|
||||
.PHONY: database pushdb
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# Clock Management Tile (CMT) - Phase Lock Loop (PLL) Fuzzer
|
||||
|
||||
FIXME: Add description.
|
||||
Bits that are part of the dynamic configration register interface (see APPNOTE
|
||||
XAPP888) are handled specially.
|
||||
|
|
|
|||
|
|
@ -6,15 +6,155 @@ from prjxray.segmaker import Segmaker
|
|||
from prjxray import verilog
|
||||
|
||||
|
||||
def bitfilter(frame, word):
|
||||
if frame < 28:
|
||||
return False
|
||||
|
||||
if frame == 25 and word == 3121:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def bus_tags(segmk, ps, site):
|
||||
for param, tagname in [('CLKOUT0_DIVIDE', 'ZCLKOUT0_DIVIDE')]:
|
||||
segmk.add_site_tag(site, 'IN_USE', ps['active'])
|
||||
|
||||
if not ps['active']:
|
||||
return
|
||||
|
||||
for k in ps:
|
||||
segmk.add_site_tag(site, 'param_' + k + '_' + str(ps[k]), 1)
|
||||
|
||||
for reg, invert in [
|
||||
('RST', 1),
|
||||
('PWRDWN', 1),
|
||||
('CLKINSEL', 0),
|
||||
]:
|
||||
opt = 'IS_{}_INVERTED'.format(reg)
|
||||
|
||||
if invert:
|
||||
segmk.add_site_tag(site, 'ZINV_' + reg, 1 ^ ps[opt])
|
||||
else:
|
||||
segmk.add_site_tag(site, 'INV_' + reg, ps[opt])
|
||||
|
||||
for opt in ['OPTIMIZED', 'HIGH', 'LOW']:
|
||||
if verilog.unquote(ps['BANDWIDTH']) == opt:
|
||||
segmk.add_site_tag(site, 'BANDWIDTH.' + opt, 1)
|
||||
elif verilog.unquote(ps['BANDWIDTH']) == 'LOW':
|
||||
segmk.add_site_tag(site, 'BANDWIDTH.' + opt, 0)
|
||||
|
||||
for opt in ['ZHOLD', 'BUF_IN', 'EXTERNAL', 'INTERNAL']:
|
||||
continue
|
||||
|
||||
opt_match = verilog.unquote(ps['COMPENSATION']) == opt
|
||||
|
||||
if ps['clkfbin_conn'] == '':
|
||||
segmk.add_site_tag(site, 'COMP.NOFB_' + opt, opt_match)
|
||||
segmk.add_site_tag(site, 'COMP.ZNOFB_' + opt, opt_match)
|
||||
continue
|
||||
|
||||
for conn in ['clk', 'clkfbout_mult_BUFG_' + ps['site'],
|
||||
'clkfbout_mult_' + ps['site']]:
|
||||
conn_match = ps['clkfbin_conn'] == conn
|
||||
segmk.add_site_tag(
|
||||
site, 'COMP.' + opt + '_' + conn + '_' + ps['site'], opt_match
|
||||
and conn_match)
|
||||
segmk.add_site_tag(
|
||||
site, 'COMP.Z' + opt + '_' + conn + '_' + ps['site'],
|
||||
not opt_match and conn_match)
|
||||
segmk.add_site_tag(
|
||||
site, 'COMP.Z' + opt + '_Z' + conn + '_' + ps['site'],
|
||||
not opt_match and not conn_match)
|
||||
segmk.add_site_tag(
|
||||
site, 'COMP.' + opt + '_Z' + conn + '_' + ps['site'], opt_match
|
||||
and not conn_match)
|
||||
|
||||
match = verilog.unquote(ps['COMPENSATION']) in ['BUF_IN', 'EXTERNAL']
|
||||
bufg_on_clkin = \
|
||||
'BUFG' in ps['clkin1_conn'] or \
|
||||
'BUFG' in ps['clkin2_conn']
|
||||
if not match:
|
||||
if verilog.unquote(ps['COMPENSATION']) == 'ZHOLD' and bufg_on_clkin:
|
||||
match = True
|
||||
segmk.add_site_tag(
|
||||
site, 'COMPENSATION.BUF_IN_OR_EXTERNAL_OR_ZHOLD_CLKIN_BUF', match)
|
||||
|
||||
match = verilog.unquote(ps['COMPENSATION']) in ['ZHOLD']
|
||||
segmk.add_site_tag(
|
||||
site, 'COMPENSATION.Z_ZHOLD_OR_CLKIN_BUF', not match
|
||||
or (match and bufg_on_clkin))
|
||||
segmk.add_site_tag(
|
||||
site, 'COMPENSATION.ZHOLD_NO_CLKIN_BUF', match and \
|
||||
not bufg_on_clkin
|
||||
)
|
||||
segmk.add_site_tag(
|
||||
site, 'COMPENSATION.ZHOLD_NO_CLKIN_BUF_NO_TOP', match and \
|
||||
not bufg_on_clkin and \
|
||||
site != "PLLE2_ADV_X0Y2"
|
||||
)
|
||||
segmk.add_site_tag(
|
||||
site, 'COMP.ZHOLD_NO_CLKIN_BUF_TOP', match and \
|
||||
not bufg_on_clkin and \
|
||||
site == "PLLE2_ADV_X0Y2"
|
||||
)
|
||||
|
||||
for opt in ['ZHOLD', 'BUF_IN', 'EXTERNAL', 'INTERNAL']:
|
||||
if opt in ['BUF_IN', 'EXTERNAL']:
|
||||
if ps['clkfbin_conn'] not in ['', 'clk']:
|
||||
continue
|
||||
|
||||
if site == "PLLE2_ADV_X0Y2" and opt == 'ZHOLD':
|
||||
segmk.add_site_tag(
|
||||
site, 'TOP.COMPENSATION.' + opt,
|
||||
verilog.unquote(ps['COMPENSATION']) == opt)
|
||||
else:
|
||||
segmk.add_site_tag(
|
||||
site, 'COMPENSATION.' + opt,
|
||||
verilog.unquote(ps['COMPENSATION']) == opt)
|
||||
segmk.add_site_tag(
|
||||
site, 'COMPENSATION.Z_' + opt,
|
||||
verilog.unquote(ps['COMPENSATION']) != opt)
|
||||
|
||||
segmk.add_site_tag(
|
||||
site, 'COMPENSATION.INTERNAL',
|
||||
verilog.unquote(ps['COMPENSATION']) in ['INTERNAL'])
|
||||
|
||||
for param in ['CLKFBOUT_MULT']:
|
||||
paramadj = int(ps[param])
|
||||
bitstr = [int(x) for x in "{0:09b}".format(paramadj)[::-1]]
|
||||
for i in range(7):
|
||||
segmk.add_site_tag(site, '%s[%u]' % (param, i), bitstr[i])
|
||||
|
||||
for param in ['CLKOUT0_DUTY_CYCLE']:
|
||||
assert ps[param][:2] == '0.', ps[param]
|
||||
assert len(ps[param]) == 5
|
||||
paramadj = int(ps[param][2:])
|
||||
bitstr = [int(x) for x in "{0:011b}".format(paramadj)[::-1]]
|
||||
|
||||
for i in range(10):
|
||||
segmk.add_site_tag(site, '%s[%u]' % (param, i), bitstr[i])
|
||||
|
||||
for param, bits in [
|
||||
('CLKOUT0_DIVIDE', 7),
|
||||
('CLKOUT1_DIVIDE', 7),
|
||||
('CLKOUT2_DIVIDE', 7),
|
||||
('CLKOUT3_DIVIDE', 7),
|
||||
('CLKOUT4_DIVIDE', 7),
|
||||
('CLKOUT5_DIVIDE', 7),
|
||||
('DIVCLK_DIVIDE', 6),
|
||||
]:
|
||||
# 1-128 => 0-127 for actual 7 bit value
|
||||
paramadj = int(ps[param]) - 1
|
||||
bitstr = [int(x) for x in "{0:07b}".format(paramadj)[::-1]]
|
||||
# FIXME: only bits 0 and 1 resolving
|
||||
# for i in range(7):
|
||||
for i in range(2):
|
||||
segmk.add_site_tag(site, '%s[%u]' % (param, i), 1 ^ bitstr[i])
|
||||
paramadj = int(ps[param])
|
||||
if paramadj < 4:
|
||||
continue
|
||||
|
||||
bitstr = [int(x) for x in "{0:09b}".format(paramadj)[::-1]]
|
||||
for i in range(bits):
|
||||
segmk.add_site_tag(site, '%s[%u]' % (param, i), bitstr[i])
|
||||
|
||||
segmk.add_site_tag(
|
||||
site, 'STARTUP_WAIT',
|
||||
verilog.unquote(ps['STARTUP_WAIT']) == 'TRUE')
|
||||
|
||||
|
||||
def run():
|
||||
|
|
@ -26,13 +166,9 @@ def run():
|
|||
f.readline()
|
||||
for l in f:
|
||||
j = json.loads(l)
|
||||
ps = j['params']
|
||||
assert j['module'] == 'my_PLLE2_ADV'
|
||||
site = verilog.unquote(ps['LOC'])
|
||||
bus_tags(segmk, j, j['site'])
|
||||
|
||||
bus_tags(segmk, ps, site)
|
||||
|
||||
segmk.compile()
|
||||
segmk.compile(bitfilter=bitfilter)
|
||||
segmk.write()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,20 +3,18 @@ read_verilog top.v
|
|||
synth_design -top top
|
||||
|
||||
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk]
|
||||
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports stb]
|
||||
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports di]
|
||||
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports do]
|
||||
|
||||
create_pblock roi
|
||||
|
||||
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
|
||||
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
|
||||
|
||||
set_property CFGBVS VCCO [current_design]
|
||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||
|
||||
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF]
|
||||
create_clock -period 10.00 [get_ports clk]
|
||||
|
||||
set net [get_nets clk_IBUF]
|
||||
if { [llength $net] > 0 } {
|
||||
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF]
|
||||
}
|
||||
|
||||
# Disable MMCM frequency etc sanity checks
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-29}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-30}]
|
||||
|
|
@ -24,10 +22,29 @@ set_property IS_ENABLED 0 [get_drc_checks {AVAL-50}]
|
|||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-53}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-126}]
|
||||
# PLL
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-43}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-161}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-78}]
|
||||
|
||||
place_design
|
||||
route_design
|
||||
|
||||
write_checkpoint -force design.dcp
|
||||
write_bitstream -force design.bit
|
||||
|
||||
set fp [open params.json "w"]
|
||||
puts $fp "\["
|
||||
foreach cell [get_cells -hierarchical -filter {REF_NAME == PLLE2_ADV}] {
|
||||
puts $fp " {"
|
||||
puts $fp " \"tile\": \"[get_tiles -of [get_sites -of $cell]]\","
|
||||
puts $fp " \"site\": \"[get_sites -of $cell]\","
|
||||
puts $fp " \"params\": {"
|
||||
foreach prop [list_property $cell] {
|
||||
puts $fp " \"$prop\": \"[get_property $prop $cell]\","
|
||||
}
|
||||
puts $fp " }"
|
||||
puts $fp " },"
|
||||
|
||||
}
|
||||
puts $fp "\]"
|
||||
close $fp
|
||||
|
|
|
|||
|
|
@ -3,102 +3,247 @@ import random
|
|||
random.seed(int(os.getenv("SEED"), 16))
|
||||
from prjxray import util
|
||||
from prjxray import verilog
|
||||
from prjxray.verilog import vrandbit, vrandbits
|
||||
import sys
|
||||
from prjxray.db import Database
|
||||
import json
|
||||
|
||||
|
||||
def gen_sites():
|
||||
for _tile_name, site_name, _site_type in sorted(util.get_roi().gen_sites(
|
||||
["PLLE2_ADV"])):
|
||||
yield site_name
|
||||
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 ['PLLE2_ADV']:
|
||||
yield site_name
|
||||
|
||||
|
||||
sites = list(gen_sites())
|
||||
DUTN = len(sites)
|
||||
DIN_N = DUTN * 8
|
||||
DOUT_N = DUTN * 8
|
||||
def main():
|
||||
f = open('params.jl', 'w')
|
||||
f.write('module,loc,params\n')
|
||||
|
||||
verilog.top_harness(DIN_N, DOUT_N)
|
||||
|
||||
f = open('params.jl', 'w')
|
||||
f.write('module,loc,params\n')
|
||||
print(
|
||||
'module roi(input clk, input [%d:0] din, output [%d:0] dout);' %
|
||||
(DIN_N - 1, DOUT_N - 1))
|
||||
|
||||
for loci, site in enumerate(sites):
|
||||
|
||||
ports = {
|
||||
'clk': 'clk',
|
||||
'din': 'din[ %d +: 8]' % (8 * loci, ),
|
||||
'dout': 'dout[ %d +: 8]' % (8 * loci, ),
|
||||
}
|
||||
|
||||
params = {
|
||||
"CLKOUT0_DIVIDE": random.randint(1, 128),
|
||||
}
|
||||
|
||||
modname = "my_PLLE2_ADV"
|
||||
verilog.instance(modname, "inst_%u" % loci, ports, params=params)
|
||||
# LOC isn't support
|
||||
params["LOC"] = verilog.quote(site)
|
||||
|
||||
j = {'module': modname, 'i': loci, 'params': params}
|
||||
f.write('%s\n' % (json.dumps(j)))
|
||||
print('')
|
||||
|
||||
f.close()
|
||||
print(
|
||||
'''endmodule
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
''')
|
||||
|
||||
print(
|
||||
'''
|
||||
module my_PLLE2_ADV (input clk, input [7:0] din, output [7:0] dout);
|
||||
parameter CLKOUT0_DIVIDE = 1;
|
||||
parameter CLKOUT1_DIVIDE = 1;
|
||||
parameter CLKOUT2_DIVIDE = 1;
|
||||
parameter CLKOUT3_DIVIDE = 1;
|
||||
parameter CLKOUT4_DIVIDE = 1;
|
||||
parameter CLKOUT5_DIVIDE = 1;
|
||||
parameter DIVCLK_DIVIDE = 1;
|
||||
parameter CLKFBOUT_MULT = 5;
|
||||
print(
|
||||
"""module top(input clk);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT1 dummy();
|
||||
""")
|
||||
|
||||
for site in sorted(gen_sites()):
|
||||
params = {
|
||||
"site":
|
||||
site,
|
||||
'active':
|
||||
random.random() > .2,
|
||||
"clkin1_conn":
|
||||
random.choice((
|
||||
"clkfbout_mult_BUFG_" + site,
|
||||
"clk",
|
||||
)),
|
||||
"clkin2_conn":
|
||||
random.choice((
|
||||
"clkfbout_mult_BUFG_" + site,
|
||||
"clk",
|
||||
)),
|
||||
"dclk_conn":
|
||||
random.choice((
|
||||
"0",
|
||||
"clk",
|
||||
)),
|
||||
"dwe_conn":
|
||||
random.choice((
|
||||
"",
|
||||
"1",
|
||||
"0",
|
||||
"dwe_" + site,
|
||||
"den_" + site,
|
||||
)),
|
||||
"den_conn":
|
||||
random.choice((
|
||||
"",
|
||||
"1",
|
||||
"0",
|
||||
"den_" + site,
|
||||
)),
|
||||
"daddr4_conn":
|
||||
random.choice((
|
||||
"0",
|
||||
"dwe_" + site,
|
||||
)),
|
||||
"IS_RST_INVERTED":
|
||||
random.randint(0, 1),
|
||||
"IS_PWRDWN_INVERTED":
|
||||
random.randint(0, 1),
|
||||
"IS_CLKINSEL_INVERTED":
|
||||
random.randint(0, 1),
|
||||
"CLKFBOUT_MULT":
|
||||
random.randint(2, 4),
|
||||
"CLKOUT0_DIVIDE":
|
||||
random.randint(1, 128),
|
||||
"CLKOUT1_DIVIDE":
|
||||
random.randint(1, 128),
|
||||
"CLKOUT2_DIVIDE":
|
||||
random.randint(1, 128),
|
||||
"CLKOUT3_DIVIDE":
|
||||
random.randint(1, 128),
|
||||
"CLKOUT4_DIVIDE":
|
||||
random.randint(1, 128),
|
||||
"CLKOUT5_DIVIDE":
|
||||
random.randint(1, 128),
|
||||
"DIVCLK_DIVIDE":
|
||||
random.randint(1, 5),
|
||||
"CLKOUT0_DUTY_CYCLE":
|
||||
"0.500",
|
||||
"STARTUP_WAIT":
|
||||
verilog.quote('TRUE' if random.randint(0, 1) else 'FALSE'),
|
||||
"COMPENSATION":
|
||||
verilog.quote(
|
||||
random.choice((
|
||||
'ZHOLD',
|
||||
'BUF_IN',
|
||||
'EXTERNAL',
|
||||
'INTERNAL',
|
||||
))),
|
||||
"BANDWIDTH":
|
||||
verilog.quote(random.choice((
|
||||
'OPTIMIZED',
|
||||
'HIGH',
|
||||
'LOW',
|
||||
))),
|
||||
}
|
||||
|
||||
if verilog.unquote(params['COMPENSATION']) == 'ZHOLD':
|
||||
params['clkfbin_conn'] = random.choice(
|
||||
(
|
||||
"",
|
||||
"clkfbout_mult_BUFG_" + site,
|
||||
))
|
||||
elif verilog.unquote(params['COMPENSATION']) == 'INTERNAL':
|
||||
params['clkfbin_conn'] = random.choice(
|
||||
(
|
||||
"",
|
||||
"clkfbout_mult_" + site,
|
||||
))
|
||||
else:
|
||||
params['clkfbin_conn'] = random.choice(
|
||||
("", "clk", "clkfbout_mult_BUFG_" + site))
|
||||
|
||||
f.write('%s\n' % (json.dumps(params)))
|
||||
|
||||
if not params['active']:
|
||||
continue
|
||||
|
||||
print(
|
||||
"""
|
||||
|
||||
wire den_{site};
|
||||
wire dwe_{site};
|
||||
|
||||
LUT1 den_lut_{site} (
|
||||
.O(den_{site})
|
||||
);
|
||||
|
||||
LUT1 dwe_lut_{site} (
|
||||
.O(dwe_{site})
|
||||
);
|
||||
|
||||
wire clkfbout_mult_{site};
|
||||
wire clkfbout_mult_BUFG_{site};
|
||||
wire clkout0_{site};
|
||||
wire clkout1_{site};
|
||||
wire clkout2_{site};
|
||||
wire clkout3_{site};
|
||||
wire clkout4_{site};
|
||||
wire clkout5_{site};
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
PLLE2_ADV #(
|
||||
.CLKOUT0_DIVIDE(CLKOUT0_DIVIDE),
|
||||
.CLKOUT1_DIVIDE(CLKOUT1_DIVIDE),
|
||||
.CLKOUT2_DIVIDE(CLKOUT2_DIVIDE),
|
||||
.CLKOUT3_DIVIDE(CLKOUT3_DIVIDE),
|
||||
.CLKOUT4_DIVIDE(CLKOUT4_DIVIDE),
|
||||
.CLKOUT5_DIVIDE(CLKOUT5_DIVIDE),
|
||||
.DIVCLK_DIVIDE(DIVCLK_DIVIDE),
|
||||
.CLKFBOUT_MULT(CLKFBOUT_MULT)
|
||||
) dut(
|
||||
.CLKFBOUT(),
|
||||
.CLKOUT0(dout[0]),
|
||||
.CLKOUT1(),
|
||||
.CLKOUT2(),
|
||||
.CLKOUT3(),
|
||||
.CLKOUT4(),
|
||||
.CLKOUT5(),
|
||||
.IS_RST_INVERTED({IS_RST_INVERTED}),
|
||||
.IS_PWRDWN_INVERTED({IS_PWRDWN_INVERTED}),
|
||||
.IS_CLKINSEL_INVERTED({IS_CLKINSEL_INVERTED}),
|
||||
.CLKOUT0_DIVIDE({CLKOUT0_DIVIDE}),
|
||||
.CLKOUT1_DIVIDE({CLKOUT1_DIVIDE}),
|
||||
.CLKOUT2_DIVIDE({CLKOUT2_DIVIDE}),
|
||||
.CLKOUT3_DIVIDE({CLKOUT3_DIVIDE}),
|
||||
.CLKOUT4_DIVIDE({CLKOUT4_DIVIDE}),
|
||||
.CLKOUT5_DIVIDE({CLKOUT5_DIVIDE}),
|
||||
.CLKFBOUT_MULT({CLKFBOUT_MULT}),
|
||||
.DIVCLK_DIVIDE({DIVCLK_DIVIDE}),
|
||||
.STARTUP_WAIT({STARTUP_WAIT}),
|
||||
.CLKOUT0_DUTY_CYCLE({CLKOUT0_DUTY_CYCLE}),
|
||||
.COMPENSATION({COMPENSATION}),
|
||||
.BANDWIDTH({BANDWIDTH}),
|
||||
.CLKIN1_PERIOD(10.0),
|
||||
.CLKIN2_PERIOD(10.0)
|
||||
) pll_{site} (
|
||||
.CLKFBOUT(clkfbout_mult_{site}),
|
||||
.CLKOUT0(clkout0_{site}),
|
||||
.CLKOUT1(clkout1_{site}),
|
||||
.CLKOUT2(clkout2_{site}),
|
||||
.CLKOUT3(clkout3_{site}),
|
||||
.CLKOUT4(clkout4_{site}),
|
||||
.CLKOUT5(clkout5_{site}),
|
||||
.DRDY(),
|
||||
.LOCKED(),
|
||||
.DO(),
|
||||
.CLKFBIN(),
|
||||
.CLKIN1(),
|
||||
.CLKIN2(),
|
||||
.CLKFBIN({clkfbin_conn}),
|
||||
.CLKIN1({clkin1_conn}),
|
||||
.CLKIN2({clkin2_conn}),
|
||||
.CLKINSEL(),
|
||||
.DCLK(),
|
||||
.DEN(),
|
||||
.DWE(),
|
||||
.DCLK({dclk_conn}),
|
||||
.DEN({den_conn}),
|
||||
.DWE({dwe_conn}),
|
||||
.PWRDWN(),
|
||||
.RST(din[0]),
|
||||
.RST(),
|
||||
.DI(),
|
||||
.DADDR());
|
||||
endmodule
|
||||
''')
|
||||
.DADDR({{7{{ {daddr4_conn} }} }}));
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFG bufg_{site} (
|
||||
.I(clkfbout_mult_{site}),
|
||||
.O(clkfbout_mult_BUFG_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
FDRE reg_clkfbout_mult_{site} (
|
||||
.C(clkfbout_mult_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
FDRE reg_clkout0_{site} (
|
||||
.C(clkout0_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
FDRE reg_clkout1_{site} (
|
||||
.C(clkout1_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
FDRE reg_clkout2_{site} (
|
||||
.C(clkout2_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
FDRE reg_clkout3_{site} (
|
||||
.C(clkout3_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
FDRE reg_clkout4_{site} (
|
||||
.C(clkout4_{site})
|
||||
);
|
||||
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
FDRE reg_clkout5_{site} (
|
||||
.C(clkout5_{site})
|
||||
);
|
||||
""".format(**params))
|
||||
|
||||
print('endmodule')
|
||||
|
||||
f.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,284 @@
|
|||
import argparse
|
||||
|
||||
REGISTER_LAYOUT = {
|
||||
'CLKOUT1': [
|
||||
('LOW_TIME', 6),
|
||||
('HIGH_TIME', 6),
|
||||
('OUTPUT_ENABLE', 1),
|
||||
('PHASE_MUX', 3),
|
||||
],
|
||||
'CLKOUT2': [
|
||||
('DELAY_TIME', 6),
|
||||
('NO_COUNT', 1),
|
||||
('EDGE', 1),
|
||||
('MX', 2),
|
||||
('FRAC_WF_R', 1),
|
||||
('FRAC_EN', 1),
|
||||
('FRAC', 3),
|
||||
('RESERVED', 1),
|
||||
],
|
||||
'DIVCLK': [
|
||||
('LOW_TIME', 6),
|
||||
('HIGH_TIME', 6),
|
||||
('NO_COUNT', 1),
|
||||
('EDGE', 1),
|
||||
('RESERVED', 2),
|
||||
],
|
||||
'LOCKREG1': [
|
||||
('LKTABLE', 10, 20),
|
||||
('LOCKREG1_RESERVED', 6, 0),
|
||||
],
|
||||
'LOCKREG2': [
|
||||
('LKTABLE', 10, 0),
|
||||
('LKTABLE', 5, 30),
|
||||
('LOCKREG2_RESERVED', 1, 0),
|
||||
],
|
||||
'LOCKREG3': [
|
||||
('LKTABLE', 10, 10),
|
||||
('LKTABLE', 5, 35),
|
||||
('LOCKREG3_RESERVED', 1, 0),
|
||||
],
|
||||
'FILTREG1': [
|
||||
('FILTREG1_RESERVED', 8, 0),
|
||||
('TABLE', 1, 6),
|
||||
('FILTREG1_RESERVED', 2, 8),
|
||||
('TABLE', 2, 7),
|
||||
('FILTREG1_RESERVED', 2, 10),
|
||||
('TABLE', 1, 9),
|
||||
],
|
||||
'FILTREG2': [
|
||||
('FILTREG2_RESERVED', 4, 0),
|
||||
('TABLE', 1, 0),
|
||||
('FILTREG2_RESERVED', 2, 4),
|
||||
('TABLE', 2, 1),
|
||||
('FILTREG2_RESERVED', 2, 6),
|
||||
('TABLE', 2, 3),
|
||||
('FILTREG2_RESERVED', 2, 8),
|
||||
('TABLE', 1, 5),
|
||||
],
|
||||
'POWER_REG': [
|
||||
('POWER_REG', 16),
|
||||
],
|
||||
}
|
||||
|
||||
BASE_OFFSET = 0x00
|
||||
REGISTER_MAP = []
|
||||
|
||||
REGISTER_MAP.append(None)
|
||||
REGISTER_MAP.append(None)
|
||||
|
||||
for idx in range(3):
|
||||
REGISTER_MAP.append(None)
|
||||
|
||||
REGISTER_MAP.append(None)
|
||||
|
||||
# 0x06 - 0x15
|
||||
for output in ['CLKOUT5', 'CLKOUT0', 'CLKOUT1', 'CLKOUT2', 'CLKOUT3',
|
||||
'CLKOUT4', None, 'CLKFBOUT']:
|
||||
if output is not None:
|
||||
REGISTER_MAP.append(('CLKOUT1', output))
|
||||
REGISTER_MAP.append(('CLKOUT2', output))
|
||||
else:
|
||||
REGISTER_MAP.append(None)
|
||||
REGISTER_MAP.append(None)
|
||||
|
||||
# 0x16
|
||||
REGISTER_MAP.append(('DIVCLK', 'DIVCLK'))
|
||||
# 0x17
|
||||
REGISTER_MAP.append(None)
|
||||
# 0x18-0x1A
|
||||
REGISTER_MAP.append(('LOCKREG1', 'LOCKREG1'))
|
||||
REGISTER_MAP.append(('LOCKREG2', 'LOCKREG2'))
|
||||
REGISTER_MAP.append(('LOCKREG3', 'LOCKREG3'))
|
||||
|
||||
for _ in range(0x28 - 0x1A - 1):
|
||||
REGISTER_MAP.append(None)
|
||||
|
||||
REGISTER_MAP.append(('POWER_REG', 'POWER_REG'))
|
||||
|
||||
for _ in range(0x4E - 0x28 - 1):
|
||||
REGISTER_MAP.append(None)
|
||||
|
||||
# 0x4E - 0x4F
|
||||
REGISTER_MAP.append(('FILTREG1', 'FILTREG1'))
|
||||
REGISTER_MAP.append(('FILTREG2', 'FILTREG2'))
|
||||
|
||||
for _ in range(0x20):
|
||||
REGISTER_MAP.append(None)
|
||||
|
||||
|
||||
class RegisterAddress(object):
|
||||
def __init__(self, frame_offsets, bit_offset):
|
||||
self.frame_index = 0
|
||||
self.frame_offsets = frame_offsets
|
||||
self.bit_offset = bit_offset
|
||||
self.bits_used = set()
|
||||
|
||||
def next_bit(self, used=True):
|
||||
output = '{}_{}'.format(
|
||||
self.frame_offsets[self.frame_index], self.bit_offset)
|
||||
|
||||
if used:
|
||||
self.bits_used.add(output)
|
||||
|
||||
self.frame_index += 1
|
||||
if self.frame_index >= len(self.frame_offsets):
|
||||
self.frame_index = 0
|
||||
self.bit_offset += 1
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def passthrough_non_register_segbits(seg_in):
|
||||
""" Filter input segbits file and capture register base offset.
|
||||
|
||||
Some PLL bit ranges are documented registers in the PLL/MMCM dynamic
|
||||
reconfiguration iterface. These features will be generated in
|
||||
output_registers. In order for output_registers to function, it needs
|
||||
the starting bit offset of the register space, which is based off of
|
||||
base_offset_register segbit definition.
|
||||
|
||||
Other features generated in fuzzing are passed through.
|
||||
|
||||
"""
|
||||
base_offset_register = 'CMT_UPPER_T.PLLE2.CLKOUT5_DIVIDE[1]'
|
||||
|
||||
bit_offset = None
|
||||
in_use = None
|
||||
with open(seg_in, 'r') as f:
|
||||
for l in f:
|
||||
if l.startswith(base_offset_register):
|
||||
parts = l.split()
|
||||
assert len(parts) == 2
|
||||
assert parts[0] == base_offset_register
|
||||
frame_offset, bit_index = map(int, parts[1].split('_'))
|
||||
|
||||
assert frame_offset == 28
|
||||
assert bit_index > 3
|
||||
bit_offset = bit_index - 3 - 16 * 3
|
||||
|
||||
continue
|
||||
|
||||
if 'IN_USE' in l:
|
||||
assert in_use is None
|
||||
in_use = l.strip()
|
||||
continue
|
||||
|
||||
parts = l.split()
|
||||
feature_parts = parts[0].split('.')
|
||||
|
||||
if len(feature_parts) < 3:
|
||||
print(l.strip())
|
||||
continue
|
||||
|
||||
if feature_parts[2] == 'BANDWIDTH':
|
||||
continue
|
||||
|
||||
if '[' not in feature_parts[2]:
|
||||
print(l.strip())
|
||||
continue
|
||||
|
||||
base_feature = feature_parts[2].split('[')
|
||||
|
||||
if base_feature[0] in [
|
||||
'CLKOUT0_DIVIDE',
|
||||
'CLKOUT1_DIVIDE',
|
||||
'CLKOUT2_DIVIDE',
|
||||
'CLKOUT3_DIVIDE',
|
||||
'CLKOUT4_DIVIDE',
|
||||
'CLKOUT5_DIVIDE',
|
||||
'DIVCLK_DIVIDE',
|
||||
'CLKFBOUT_MULT',
|
||||
'CLKOUT0_DUTY_CYCLE',
|
||||
]:
|
||||
# These features are PLL registers, so ignore the base
|
||||
continue
|
||||
|
||||
print(l.strip())
|
||||
|
||||
assert bit_offset is not None
|
||||
assert in_use is not None
|
||||
return bit_offset, in_use
|
||||
|
||||
|
||||
def output_registers(bit_offset, in_use):
|
||||
""" Output segbits for the known PLL register space.
|
||||
|
||||
The first bit offset in the register space is required to generate this
|
||||
output.
|
||||
|
||||
"""
|
||||
reg = RegisterAddress(frame_offsets=[28, 29], bit_offset=bit_offset)
|
||||
|
||||
for idx, register in enumerate(REGISTER_MAP):
|
||||
if register is None:
|
||||
for _ in range(16):
|
||||
reg.next_bit(used=False)
|
||||
continue
|
||||
|
||||
layout, register_name = register
|
||||
|
||||
layout_bits = REGISTER_LAYOUT[layout]
|
||||
|
||||
simple_layout = len(layout_bits[0]) == 2
|
||||
|
||||
if True:
|
||||
bit_count = 0
|
||||
if simple_layout:
|
||||
for field, width in layout_bits:
|
||||
for bit in range(width):
|
||||
bit_count += 1
|
||||
|
||||
if field is None:
|
||||
reg.next_bit(used=False)
|
||||
continue
|
||||
|
||||
print(
|
||||
'CMT_UPPER_T.PLLE2.{}_{}_{}[{}] {}'.format(
|
||||
register_name, layout, field, bit,
|
||||
reg.next_bit()))
|
||||
else:
|
||||
for field, width, start_bit in layout_bits:
|
||||
for bit in range(width):
|
||||
bit_count += 1
|
||||
|
||||
if field is None:
|
||||
reg.next_bit(used=False)
|
||||
continue
|
||||
|
||||
print(
|
||||
'CMT_UPPER_T.PLLE2.{}[{}] {}'.format(
|
||||
field, start_bit + bit, reg.next_bit()))
|
||||
|
||||
assert bit_count == 16
|
||||
else:
|
||||
for bit in range(16):
|
||||
if register_name != layout or layout in ['CLKOUT1', 'CLKOUT2']:
|
||||
print(
|
||||
'CMT_UPPER_T.PLLE2.{}_{}[{}] {}'.format(
|
||||
register_name, layout, bit, reg.next_bit()))
|
||||
else:
|
||||
print(
|
||||
'CMT_UPPER_T.PLLE2.{}[{}] {}'.format(
|
||||
register_name, bit, reg.next_bit()))
|
||||
|
||||
parts = in_use.split()
|
||||
feature = parts[0]
|
||||
bits = [p for p in parts[1:] if p not in reg.bits_used]
|
||||
print('{} {}'.format(feature, ' '.join(bits)))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="")
|
||||
|
||||
parser.add_argument('--seg_in')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
bit_offset, in_use = passthrough_non_register_segbits(args.seg_in)
|
||||
|
||||
output_registers(bit_offset, in_use)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
export FUZDIR=$(shell pwd)
|
||||
PIP_TYPE?=cmt_top
|
||||
PIPLIST_TCL=$(FUZDIR)/cmt_top_upper_t.tcl
|
||||
TODO_RE=".*\.CMT_TOP_[LR]_UPPER_T_PLLE2_CLK_[^_]+_INT"
|
||||
|
||||
ifneq (${XRAY_DATABASE}, zynq7)
|
||||
MAKETODO_FLAGS=--sides "r_upper_t,l_upper_t" --pip-type ${PIP_TYPE} --seg-type cmt_top --re $(TODO_RE)
|
||||
else
|
||||
MAKETODO_FLAGS=--sides "l_upper_t" --pip-type ${PIP_TYPE} --seg-type cmt_top --re $(TODO_RE)
|
||||
endif
|
||||
N = 50
|
||||
|
||||
A_PIPLIST=cmt_top_l_upper_t.txt
|
||||
|
||||
include ../pip_loop.mk
|
||||
|
||||
build/segbits_cmt_top_l_upper_t.rdb: $(SPECIMENS_OK)
|
||||
${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_cmt_top_l_upper_t.rdb \
|
||||
$(shell find build -name segdata_cmt_top_l_upper_t.txt)
|
||||
|
||||
RDBS = build/segbits_cmt_top_l_upper_t.rdb
|
||||
|
||||
ifneq (${XRAY_DATABASE}, zynq7)
|
||||
# Target Zynq7 part has no CMT_TOP_R_UPPER_T
|
||||
build/segbits_cmt_top_r_upper_t.rdb: $(SPECIMENS_OK)
|
||||
${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_cmt_top_r_upper_t.rdb \
|
||||
$(shell find build -name segdata_cmt_top_r_upper_t.txt)
|
||||
|
||||
RDBS += build/segbits_cmt_top_r_upper_t.rdb
|
||||
endif
|
||||
|
||||
database: ${RDBS}
|
||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
|
||||
--seg-fn-in build/segbits_cmt_top_l_upper_t.rdb \
|
||||
--seg-fn-out build/segbits_cmt_top_l_upper_t.db
|
||||
|
||||
ifneq (${XRAY_DATABASE}, zynq7)
|
||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
|
||||
--seg-fn-in build/segbits_cmt_top_r_upper_t.rdb \
|
||||
--seg-fn-out build/segbits_cmt_top_r_upper_t.db
|
||||
endif
|
||||
|
||||
# Keep a copy to track iter progress
|
||||
cp build/segbits_cmt_top_l_upper_t.rdb build/$(ITER)/segbits_cmt_top_l_upper_t.rdb
|
||||
cp build/segbits_cmt_top_l_upper_t.db build/$(ITER)/segbits_cmt_top_l_upper_t.db
|
||||
ifneq (${XRAY_DATABASE}, zynq7)
|
||||
cp build/segbits_cmt_top_r_upper_t.rdb build/$(ITER)/segbits_cmt_top_r_upper_t.rdb
|
||||
cp build/segbits_cmt_top_r_upper_t.db build/$(ITER)/segbits_cmt_top_r_upper_t.db
|
||||
endif
|
||||
|
||||
|
||||
${XRAY_MASKMERGE} build/mask_cmt_top_l_upper_t.db \
|
||||
$(shell find build -name segdata_cmt_top_l_upper_t.txt)
|
||||
ifneq (${XRAY_DATABASE}, zynq7)
|
||||
${XRAY_MASKMERGE} build/mask_cmt_top_r_upper_t.db \
|
||||
$(shell find build -name segdata_cmt_top_r_upper_t.txt)
|
||||
endif
|
||||
|
||||
# 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} cmt_top_l_upper_t build/segbits_cmt_top_l_upper_t.db
|
||||
ifneq (${XRAY_DATABASE}, zynq7)
|
||||
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} cmt_top_r_upper_t build/segbits_cmt_top_r_upper_t.db
|
||||
endif
|
||||
|
||||
pushdb: database
|
||||
${XRAY_MERGEDB} cmt_top_l_upper_t build/segbits_cmt_top_l_upper_t.db
|
||||
ifneq (${XRAY_DATABASE}, zynq7)
|
||||
${XRAY_MERGEDB} cmt_top_r_upper_t build/segbits_cmt_top_r_upper_t.db
|
||||
endif
|
||||
|
||||
.PHONY: database pushdb
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
proc print_tile_pips {tile_type filename} {
|
||||
set tile [lindex [get_tiles -filter "TYPE == $tile_type"] 0]
|
||||
puts "Dumping PIPs for tile $tile ($tile_type) to $filename."
|
||||
set fp [open $filename w]
|
||||
foreach pip [lsort [get_pips -of_objects [get_tiles $tile]]] {
|
||||
set src [get_wires -uphill -of_objects $pip]
|
||||
set dst [get_wires -downhill -of_objects $pip]
|
||||
if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] == 1} {
|
||||
set src_node [get_nodes -of $src]
|
||||
set dst_node [get_nodes -of $dst]
|
||||
|
||||
if { [string first INT_INTERFACE [get_wires -of $src_node]] != -1 } {
|
||||
continue
|
||||
}
|
||||
if { [string first INT_INTERFACE [get_wires -of $dst_node]] != -1 } {
|
||||
continue
|
||||
}
|
||||
}
|
||||
puts $fp "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
|
||||
}
|
||||
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 CMT_TOP_L_UPPER_T cmt_top_l_upper_t.txt
|
||||
print_tile_pips CMT_TOP_R_UPPER_T cmt_top_r_upper_t.txt
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from prjxray.segmaker import Segmaker
|
||||
import os
|
||||
import os.path
|
||||
|
||||
|
||||
def bitfilter(frame, word):
|
||||
if frame <= 1:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
segmk = Segmaker("design.bits")
|
||||
|
||||
tiledata = {}
|
||||
pipdata = {}
|
||||
ignpip = set()
|
||||
|
||||
with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
|
||||
'cmt_top', 'cmt_top_l_upper_t.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',
|
||||
'cmt_top', 'cmt_top_r_upper_t.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('CMT_TOP'):
|
||||
continue
|
||||
|
||||
if 'UPPER_B' in tile:
|
||||
continue
|
||||
|
||||
pip_prefix, _ = pip.split(".")
|
||||
tile_from_pip, tile_type = pip_prefix.split('/')
|
||||
assert tile == tile_from_pip
|
||||
_, 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 dst.startswith('CMT_TOP_R_UPPER_T_CLK') or \
|
||||
dst.startswith('CMT_TOP_L_UPPER_T_CLK'):
|
||||
ignpip.add((src, dst))
|
||||
|
||||
for tile, pips_srcs_dsts in tiledata.items():
|
||||
tile_type = pips_srcs_dsts["type"]
|
||||
pips = pips_srcs_dsts["pips"]
|
||||
|
||||
for src, dst in pipdata[tile_type]:
|
||||
if (src, dst) in ignpip:
|
||||
pass
|
||||
elif (src, dst) in pips:
|
||||
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 1)
|
||||
elif (src, dst) not in tiledata[tile]["pips"]:
|
||||
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0)
|
||||
|
||||
internal_feedback = False
|
||||
for src, dst in [
|
||||
('CMT_TOP_L_CLKFBOUT2IN', 'CMT_TOP_R_UPPER_T_PLLE2_CLKFBIN'),
|
||||
('CMT_TOP_R_CLKFBOUT2IN', 'CMT_TOP_R_UPPER_T_PLLE2_CLKFBIN'),
|
||||
]:
|
||||
if (src, dst) in pips:
|
||||
internal_feedback = True
|
||||
|
||||
segmk.add_tile_tag(tile, "EXTERNAL_FEEDBACK", not internal_feedback)
|
||||
|
||||
segmk.compile(bitfilter=bitfilter)
|
||||
segmk.write()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
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]
|
||||
|
||||
# Disable MMCM frequency etc sanity checks
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-29}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-30}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-50}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-53}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-126}]
|
||||
# PLL
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-43}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-161}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-78}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {AVAL-81}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {PDRC-38}]
|
||||
set_property IS_ENABLED 0 [get_drc_checks {REQP-13}]
|
||||
|
||||
place_design
|
||||
route_design
|
||||
|
||||
write_checkpoint -force design.dcp
|
||||
write_bitstream -force design.bit
|
||||
write_pip_txtdata design.txt
|
||||
}
|
||||
|
||||
run
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
""" """
|
||||
import os
|
||||
import random
|
||||
random.seed(int(os.getenv("SEED"), 16))
|
||||
from prjxray import util
|
||||
from prjxray.db import Database
|
||||
|
||||
|
||||
def find_phasers_for_pll(grid, loc):
|
||||
gridinfo = grid.gridinfo_at_loc((loc[0], loc[1] + 13))
|
||||
|
||||
phasers = {
|
||||
'IN': [],
|
||||
'OUT': [],
|
||||
}
|
||||
|
||||
for site_name, site_type in gridinfo.sites.items():
|
||||
if site_type == 'PHASER_IN_PHY':
|
||||
phasers['IN'].append(site_name)
|
||||
elif site_type == 'PHASER_OUT_PHY':
|
||||
phasers['OUT'].append(site_name)
|
||||
|
||||
assert len(phasers['IN']) > 0
|
||||
assert len(phasers['OUT']) > 0
|
||||
|
||||
phasers['IN'].sort()
|
||||
phasers['OUT'].sort()
|
||||
|
||||
return phasers
|
||||
|
||||
|
||||
def gen_sites():
|
||||
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 ['PLLE2_ADV']:
|
||||
phasers = find_phasers_for_pll(grid, loc)
|
||||
yield site_name, phasers
|
||||
|
||||
|
||||
def main():
|
||||
print(
|
||||
'''
|
||||
module top();
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
LUT6 dummy();
|
||||
''')
|
||||
|
||||
bufg_count = 0
|
||||
|
||||
for site, phasers in sorted(gen_sites(), key=lambda x: x[0]):
|
||||
drive_feedback = random.randint(0, 1)
|
||||
clkfbin_src = random.choice(('BUFH', '0', '1', None))
|
||||
|
||||
if drive_feedback:
|
||||
COMPENSATION = "INTERNAL"
|
||||
else:
|
||||
if clkfbin_src in ['0', '1']:
|
||||
COMPENSATION = 'EXTERNAL'
|
||||
else:
|
||||
COMPENSATION = "ZHOLD"
|
||||
|
||||
print(
|
||||
"""
|
||||
wire clkfbin_{site};
|
||||
wire clkin1_{site};
|
||||
wire clkin2_{site};
|
||||
wire clkfbout_mult_{site};
|
||||
wire clkout0_{site};
|
||||
wire clkout1_{site};
|
||||
wire clkout2_{site};
|
||||
wire clkout3_{site};
|
||||
wire clkout4_{site};
|
||||
wire clkout5_{site};
|
||||
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
||||
PLLE2_ADV #(
|
||||
.COMPENSATION("{COMPENSATION}")
|
||||
) pll_{site} (
|
||||
.CLKFBOUT(clkfbout_mult_{site}),
|
||||
.CLKOUT0(clkout0_{site}),
|
||||
.CLKOUT1(clkout1_{site}),
|
||||
.CLKOUT2(clkout2_{site}),
|
||||
.CLKOUT3(clkout3_{site}),
|
||||
.CLKOUT4(clkout4_{site}),
|
||||
.CLKOUT5(clkout5_{site}),
|
||||
.DRDY(),
|
||||
.LOCKED(),
|
||||
.DO(),
|
||||
.CLKFBIN(clkfbin_{site}),
|
||||
.CLKIN1(clkin1_{site}),
|
||||
.CLKIN2(clkin2_{site}),
|
||||
.CLKINSEL(),
|
||||
.DCLK(),
|
||||
.DEN(),
|
||||
.DWE(),
|
||||
.PWRDWN(),
|
||||
.RST(),
|
||||
.DI(),
|
||||
.DADDR());
|
||||
""".format(site=site, COMPENSATION=COMPENSATION))
|
||||
|
||||
for clkout in range(4, 6):
|
||||
# CLKOUT4 and CLKOUT5 can only drive one signal type
|
||||
if random.randint(0, 1) and bufg_count < 16:
|
||||
bufg_count += 1
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFG (
|
||||
.I(clkout{idx}_{site})
|
||||
);""".format(idx=clkout, site=site))
|
||||
|
||||
any_phaser = False
|
||||
|
||||
for clkout in range(4):
|
||||
# CLKOUT0-CLKOUT3 can drive:
|
||||
# - Global drivers (e.g. BUFG)
|
||||
# - PHASER_[IN|OUT]_[CA|DB]_FREQREFCLK via BB_[0-3]
|
||||
drive_bufg = random.randint(0, 1) and bufg_count < 16
|
||||
drive_phaser = random.randint(0, 1)
|
||||
|
||||
if drive_bufg:
|
||||
bufg_count += 1
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFG (
|
||||
.I(clkout{idx}_{site})
|
||||
);""".format(idx=clkout, site=site))
|
||||
|
||||
if drive_phaser and not any_phaser and False:
|
||||
any_phaser = True
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH, LOC="{phaser_loc}" *)
|
||||
PHASER_OUT phaser_{site}(
|
||||
.FREQREFCLK(clkout{idx}_{site})
|
||||
);""".format(idx=clkout, site=site, phaser_loc=phasers['OUT'][0]))
|
||||
|
||||
drive_bufg = random.randint(0, 1) and bufg_count < 16
|
||||
|
||||
if drive_bufg and clkfbin_src not in ['BUFH', 'BUFR']:
|
||||
bufg_count += 1
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFG (
|
||||
.I(clkfbout_mult_{site})
|
||||
);""".format(site=site))
|
||||
|
||||
if drive_feedback:
|
||||
print(
|
||||
"""
|
||||
assign clkfbin_{site} = clkfbout_mult_{site};
|
||||
""".format(site=site))
|
||||
else:
|
||||
# If CLKFBIN is not using CLKFBOUT feedback, can be connected to:
|
||||
# - BUFHCE/BUFR using dedicated path
|
||||
# - Switch box clock port
|
||||
|
||||
if clkfbin_src is None:
|
||||
pass
|
||||
elif clkfbin_src == 'BUFH':
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFH (
|
||||
.I(clkfbout_mult_{site}),
|
||||
.O(clkfbin_{site})
|
||||
);""".format(site=site))
|
||||
elif clkfbin_src == 'BUFR':
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFR (
|
||||
.I(clkfbout_mult_{site}),
|
||||
.O(clkfbin_{site})
|
||||
);""".format(site=site))
|
||||
elif clkfbin_src == '0':
|
||||
print(
|
||||
"""
|
||||
assign clkfbin_{site} = 0;
|
||||
""".format(site=site))
|
||||
elif clkfbin_src == '1':
|
||||
print(
|
||||
"""
|
||||
assign clkfbin_{site} = 1;
|
||||
""".format(site=site))
|
||||
else:
|
||||
assert False, clkfbin_src
|
||||
|
||||
clkin_is_none = False
|
||||
|
||||
for clkin in range(2):
|
||||
clkin_src = random.choice((
|
||||
'BUFH',
|
||||
'BUFR',
|
||||
'0',
|
||||
'1',
|
||||
None,
|
||||
))
|
||||
if clkin == 1 and clkin_is_none and clkin_src is None:
|
||||
clkin_src = 'BUFH'
|
||||
|
||||
if clkin_src is None:
|
||||
pass
|
||||
elif clkin_src == 'BUFH':
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFH (
|
||||
.O(clkin{idx}_{site})
|
||||
);""".format(idx=clkin + 1, site=site))
|
||||
elif clkin_src == 'BUFR':
|
||||
print(
|
||||
"""
|
||||
(* KEEP, DONT_TOUCH *)
|
||||
BUFR (
|
||||
.O(clkin{idx}_{site})
|
||||
);""".format(idx=clkin + 1, site=site))
|
||||
elif clkin_src == '0':
|
||||
print(
|
||||
"""
|
||||
assign clkin{idx}_{site} = 0;
|
||||
""".format(idx=clkin + 1, site=site))
|
||||
elif clkin_src == '1':
|
||||
print(
|
||||
"""
|
||||
assign clkin{idx}_{site} = 1;
|
||||
""".format(idx=clkin + 1, site=site))
|
||||
else:
|
||||
assert False, clkfbin_src
|
||||
|
||||
print("endmodule")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -83,6 +83,8 @@ $(eval $(call fuzzer,027-bram36-config,005-tilegrid))
|
|||
$(eval $(call fuzzer,028-fifo-config,005-tilegrid))
|
||||
$(eval $(call fuzzer,029-bram-fifo-config,005-tilegrid))
|
||||
$(eval $(call fuzzer,030-iob,005-tilegrid))
|
||||
$(eval $(call fuzzer,032-cmt-pll,005-tilegrid))
|
||||
$(eval $(call fuzzer,034-cmt-pll-pips,005-tilegrid))
|
||||
$(eval $(call fuzzer,035-iob-ilogic,005-tilegrid))
|
||||
$(eval $(call fuzzer,036-iob-ologic,005-tilegrid))
|
||||
$(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid))
|
||||
|
|
|
|||
|
|
@ -339,6 +339,8 @@ class Segmaker:
|
|||
-LIOB33 => IOB33
|
||||
'''
|
||||
tile_type_norm = re.sub("(_TOP|_BOT|LL|LM)?_[LR]$", "", tile_type)
|
||||
tile_type_norm = re.sub(
|
||||
"_TOP_[LR]_UPPER", "_UPPER", tile_type_norm)
|
||||
|
||||
if tile_type_norm in ['LIOB33', 'RIOB33']:
|
||||
tile_type_norm = 'IOB33'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import os, sys
|
||||
from prjxray import util
|
||||
|
||||
|
||||
|
|
@ -21,9 +21,11 @@ def run(fn_ins, fn_out, strict=False, track_origin=False, verbose=False):
|
|||
if tag in tags:
|
||||
orig_bits, orig_line, orig_origin = tags[tag]
|
||||
if orig_bits != bits:
|
||||
print("WARNING: got duplicate tag %s" % (tag, ))
|
||||
print(" Orig line: %s" % orig_line)
|
||||
print(" New line : %s" % line)
|
||||
print(
|
||||
"WARNING: got duplicate tag %s" % (tag, ),
|
||||
file=sys.stderr)
|
||||
print(" Orig line: %s" % orig_line, file=sys.stderr)
|
||||
print(" New line : %s" % line, file=sys.stderr)
|
||||
assert not strict, "strict: got duplicate tag"
|
||||
origin = os.path.basename(os.getcwd())
|
||||
if track_origin and orig_origin != origin:
|
||||
|
|
@ -31,9 +33,11 @@ def run(fn_ins, fn_out, strict=False, track_origin=False, verbose=False):
|
|||
if bits in bitss:
|
||||
orig_tag, orig_line = bitss[bits]
|
||||
if orig_tag != tag:
|
||||
print("WARNING: got duplicate bits %s" % (bits, ))
|
||||
print(" Orig line: %s" % orig_line)
|
||||
print(" New line : %s" % line)
|
||||
print(
|
||||
"WARNING: got duplicate bits %s" % (bits, ),
|
||||
file=sys.stderr)
|
||||
print(" Orig line: %s" % orig_line, file=sys.stderr)
|
||||
print(" New line : %s" % line, file=sys.stderr)
|
||||
assert not strict, "strict: got duplicate bits"
|
||||
|
||||
if track_origin and origin is None:
|
||||
|
|
|
|||
|
|
@ -114,6 +114,12 @@ case "$1" in
|
|||
riob33)
|
||||
sed < "$2" > "$tmp1" -e 's/^IOB33\./RIOB33./' ;;
|
||||
|
||||
cmt_top_r_upper_t)
|
||||
sed < "$2" > "$tmp1" -e 's/^CMT_UPPER_T\./CMT_TOP_R_UPPER_T./' ;;
|
||||
|
||||
cmt_top_l_upper_t)
|
||||
sed < "$2" > "$tmp1" -e 's/^CMT_UPPER_T\./CMT_TOP_L_UPPER_T./' ;;
|
||||
|
||||
mask_*)
|
||||
db=$XRAY_DATABASE_DIR/$XRAY_DATABASE/$1.db
|
||||
ismask=true
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ def run(fnin, fnout=None, strict=False, verbose=False):
|
|||
if mode != "always":
|
||||
assert not mode, "strict: got ill defined line: %s" % (line, )
|
||||
if tag in tags:
|
||||
print("Original line: %s" % tags[tag])
|
||||
print("New line: %s" % line)
|
||||
print("Original line: %s" % tags[tag], file=sys.stderr)
|
||||
print("New line: %s" % line, file=sys.stderr)
|
||||
assert 0, "strict: got duplicate tag %s" % (tag, )
|
||||
assert bits not in bitss, "strict: got duplicate bits %s: %s %s" % (
|
||||
bits, tag, bitss[bits])
|
||||
|
|
|
|||
Loading…
Reference in New Issue