mirror of https://github.com/openXC7/prjxray.git
Complete initial PLL fuzzer.
This solves for all unknown bits, but results in a large "IN_USE" feature for apparently constant bits. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
bc822f8337
commit
30648d554a
|
|
@ -79,7 +79,7 @@ def run(fn_in, fn_out, verbose=False):
|
||||||
("iob/build/segbits_tilegrid.tdb", 42, 4),
|
("iob/build/segbits_tilegrid.tdb", 42, 4),
|
||||||
("ioi/build/segbits_tilegrid.tdb", 42, 4),
|
("ioi/build/segbits_tilegrid.tdb", 42, 4),
|
||||||
("mmcm/build/segbits_tilegrid.tdb", 30, 101),
|
("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),
|
("monitor/build/segbits_tilegrid.tdb", 30, 101),
|
||||||
("bram/build/segbits_tilegrid.tdb", 28, 10),
|
("bram/build/segbits_tilegrid.tdb", 28, 10),
|
||||||
("bram_block/build/segbits_tilegrid.tdb", 128, 10),
|
("bram_block/build/segbits_tilegrid.tdb", 128, 10),
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
N ?= 5
|
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
|
include ../fuzzaddr/common.mk
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
# read/write width is relatively slow to resolve
|
|
||||||
# Even slower with multi bit masks...
|
|
||||||
N := 50
|
N := 50
|
||||||
include ../fuzzer.mk
|
include ../fuzzer.mk
|
||||||
|
|
||||||
database: build/segbits_cmt_top_upper_t.db
|
database: build/segbits_cmt_top_upper_t.db
|
||||||
|
|
||||||
build/segbits_cmt_top_upper_t.rdb: $(SPECIMENS_OK)
|
build/segbits_cmt_top_upper_t.rdb: $(SPECIMENS_OK)
|
||||||
${XRAY_SEGMATCH} -o build/segbits_cmt_top_upper_t.rdb \
|
${XRAY_SEGMATCH} -c 150 -o build/segbits_cmt_top_upper_t.rdb \
|
||||||
$(addsuffix /segdata_cmt_top_r_upper_t.txt,$(SPECIMENS)) \
|
$(addsuffix /segdata_cmt_top_r_upper_t.txt,$(SPECIMENS)) \
|
||||||
$(addsuffix /segdata_cmt_top_l_upper_t.txt,$(SPECIMENS))
|
$(addsuffix /segdata_cmt_top_l_upper_t.txt,$(SPECIMENS))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ from prjxray import verilog
|
||||||
|
|
||||||
|
|
||||||
def bitfilter(frame, word):
|
def bitfilter(frame, word):
|
||||||
|
if frame < 28:
|
||||||
|
return False
|
||||||
|
|
||||||
if frame == 25 and word == 3121:
|
if frame == 25 and word == 3121:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -14,12 +17,14 @@ def bitfilter(frame, word):
|
||||||
|
|
||||||
|
|
||||||
def bus_tags(segmk, ps, site):
|
def bus_tags(segmk, ps, site):
|
||||||
|
segmk.add_site_tag(site, 'IN_USE', ps['active'])
|
||||||
|
|
||||||
|
if not ps['active']:
|
||||||
|
return
|
||||||
|
|
||||||
for k in ps:
|
for k in ps:
|
||||||
segmk.add_site_tag(site, 'param_' + k + '_' + str(ps[k]), 1)
|
segmk.add_site_tag(site, 'param_' + k + '_' + str(ps[k]), 1)
|
||||||
|
|
||||||
segmk.add_site_tag(site, 'DWE_CONNECTED',
|
|
||||||
ps['dwe_conn'].startswith('dwe_') or ps['dwe_conn'].startswith('den_'))
|
|
||||||
|
|
||||||
for reg, invert in [
|
for reg, invert in [
|
||||||
('RST', 1),
|
('RST', 1),
|
||||||
('PWRDWN', 1),
|
('PWRDWN', 1),
|
||||||
|
|
@ -32,18 +37,72 @@ def bus_tags(segmk, ps, site):
|
||||||
else:
|
else:
|
||||||
segmk.add_site_tag(site, 'INV_' + reg, ps[opt])
|
segmk.add_site_tag(site, 'INV_' + reg, ps[opt])
|
||||||
|
|
||||||
|
|
||||||
for opt in ['OPTIMIZED', 'HIGH', 'LOW']:
|
for opt in ['OPTIMIZED', 'HIGH', 'LOW']:
|
||||||
if verilog.unquote(ps['BANDWIDTH']) == opt:
|
if verilog.unquote(ps['BANDWIDTH']) == opt:
|
||||||
segmk.add_site_tag(
|
segmk.add_site_tag(site, 'BANDWIDTH.' + opt, 1)
|
||||||
site, 'BANDWIDTH.' + opt,
|
|
||||||
1)
|
|
||||||
elif verilog.unquote(ps['BANDWIDTH']) == 'LOW':
|
elif verilog.unquote(ps['BANDWIDTH']) == 'LOW':
|
||||||
segmk.add_site_tag(
|
segmk.add_site_tag(site, 'BANDWIDTH.' + opt, 0)
|
||||||
site, 'BANDWIDTH.' + opt,
|
|
||||||
0)
|
|
||||||
|
|
||||||
for opt in ['ZHOLD', 'BUF_IN', 'EXTERNAL', 'INTERNAL']:
|
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':
|
if site == "PLLE2_ADV_X0Y2" and opt == 'ZHOLD':
|
||||||
segmk.add_site_tag(
|
segmk.add_site_tag(
|
||||||
site, 'TOP.COMPENSATION.' + opt,
|
site, 'TOP.COMPENSATION.' + opt,
|
||||||
|
|
@ -56,14 +115,9 @@ def bus_tags(segmk, ps, site):
|
||||||
site, 'COMPENSATION.Z_' + opt,
|
site, 'COMPENSATION.Z_' + opt,
|
||||||
verilog.unquote(ps['COMPENSATION']) != opt)
|
verilog.unquote(ps['COMPENSATION']) != opt)
|
||||||
|
|
||||||
match = "TRUE" == verilog.unquote(ps['STARTUP_WAIT']) and \
|
|
||||||
opt == verilog.unquote(ps['COMPENSATION'])
|
|
||||||
segmk.add_site_tag(site, "STARTUP_WAIT_AND_" + opt,
|
|
||||||
match)
|
|
||||||
|
|
||||||
segmk.add_site_tag(
|
segmk.add_site_tag(
|
||||||
site, 'COMPENSATION.BUF_IN_OR_EXTERNAL',
|
site, 'COMPENSATION.INTERNAL',
|
||||||
verilog.unquote(ps['COMPENSATION']) in ['BUF_IN', 'EXTERNAL'])
|
verilog.unquote(ps['COMPENSATION']) in ['INTERNAL'])
|
||||||
|
|
||||||
for param in ['CLKFBOUT_MULT']:
|
for param in ['CLKFBOUT_MULT']:
|
||||||
paramadj = int(ps[param])
|
paramadj = int(ps[param])
|
||||||
|
|
|
||||||
|
|
@ -29,24 +29,40 @@ def main():
|
||||||
params = {
|
params = {
|
||||||
"site":
|
"site":
|
||||||
site,
|
site,
|
||||||
"dclk_conn": random.choice((
|
'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",
|
"0",
|
||||||
"clk",
|
"clk",
|
||||||
)),
|
)),
|
||||||
"dwe_conn": random.choice((
|
"dwe_conn":
|
||||||
|
random.choice((
|
||||||
"",
|
"",
|
||||||
"1",
|
"1",
|
||||||
"0",
|
"0",
|
||||||
"dwe_" + site,
|
"dwe_" + site,
|
||||||
"den_" + site,
|
"den_" + site,
|
||||||
)),
|
)),
|
||||||
"den_conn": random.choice((
|
"den_conn":
|
||||||
|
random.choice((
|
||||||
"",
|
"",
|
||||||
"1",
|
"1",
|
||||||
"0",
|
"0",
|
||||||
"den_" + site,
|
"den_" + site,
|
||||||
)),
|
)),
|
||||||
"daddr4_conn": random.choice((
|
"daddr4_conn":
|
||||||
|
random.choice((
|
||||||
"0",
|
"0",
|
||||||
"dwe_" + site,
|
"dwe_" + site,
|
||||||
)),
|
)),
|
||||||
|
|
@ -85,15 +101,34 @@ def main():
|
||||||
'INTERNAL',
|
'INTERNAL',
|
||||||
))),
|
))),
|
||||||
"BANDWIDTH":
|
"BANDWIDTH":
|
||||||
verilog.quote(
|
verilog.quote(random.choice((
|
||||||
random.choice((
|
|
||||||
'OPTIMIZED',
|
'OPTIMIZED',
|
||||||
'HIGH',
|
'HIGH',
|
||||||
'LOW',
|
'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)))
|
f.write('%s\n' % (json.dumps(params)))
|
||||||
|
|
||||||
|
if not params['active']:
|
||||||
|
continue
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -109,6 +144,7 @@ def main():
|
||||||
);
|
);
|
||||||
|
|
||||||
wire clkfbout_mult_{site};
|
wire clkfbout_mult_{site};
|
||||||
|
wire clkfbout_mult_BUFG_{site};
|
||||||
wire clkout0_{site};
|
wire clkout0_{site};
|
||||||
wire clkout1_{site};
|
wire clkout1_{site};
|
||||||
wire clkout2_{site};
|
wire clkout2_{site};
|
||||||
|
|
@ -131,7 +167,9 @@ def main():
|
||||||
.STARTUP_WAIT({STARTUP_WAIT}),
|
.STARTUP_WAIT({STARTUP_WAIT}),
|
||||||
.CLKOUT0_DUTY_CYCLE({CLKOUT0_DUTY_CYCLE}),
|
.CLKOUT0_DUTY_CYCLE({CLKOUT0_DUTY_CYCLE}),
|
||||||
.COMPENSATION({COMPENSATION}),
|
.COMPENSATION({COMPENSATION}),
|
||||||
.BANDWIDTH({BANDWIDTH})
|
.BANDWIDTH({BANDWIDTH}),
|
||||||
|
.CLKIN1_PERIOD(10.0),
|
||||||
|
.CLKIN2_PERIOD(10.0)
|
||||||
) pll_{site} (
|
) pll_{site} (
|
||||||
.CLKFBOUT(clkfbout_mult_{site}),
|
.CLKFBOUT(clkfbout_mult_{site}),
|
||||||
.CLKOUT0(clkout0_{site}),
|
.CLKOUT0(clkout0_{site}),
|
||||||
|
|
@ -143,9 +181,9 @@ def main():
|
||||||
.DRDY(),
|
.DRDY(),
|
||||||
.LOCKED(),
|
.LOCKED(),
|
||||||
.DO(),
|
.DO(),
|
||||||
.CLKFBIN(),
|
.CLKFBIN({clkfbin_conn}),
|
||||||
.CLKIN1(clk),
|
.CLKIN1({clkin1_conn}),
|
||||||
.CLKIN2(),
|
.CLKIN2({clkin2_conn}),
|
||||||
.CLKINSEL(),
|
.CLKINSEL(),
|
||||||
.DCLK({dclk_conn}),
|
.DCLK({dclk_conn}),
|
||||||
.DEN({den_conn}),
|
.DEN({den_conn}),
|
||||||
|
|
@ -155,6 +193,12 @@ def main():
|
||||||
.DI(),
|
.DI(),
|
||||||
.DADDR({{7{{ {daddr4_conn} }} }}));
|
.DADDR({{7{{ {daddr4_conn} }} }}));
|
||||||
|
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
BUFG bufg_{site} (
|
||||||
|
.I(clkfbout_mult_{site}),
|
||||||
|
.O(clkfbout_mult_BUFG_{site})
|
||||||
|
);
|
||||||
|
|
||||||
(* KEEP, DONT_TOUCH *)
|
(* KEEP, DONT_TOUCH *)
|
||||||
FDRE reg_clkfbout_mult_{site} (
|
FDRE reg_clkfbout_mult_{site} (
|
||||||
.C(clkfbout_mult_{site})
|
.C(clkfbout_mult_{site})
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ REGISTER_LAYOUT = {
|
||||||
'CLKOUT1': [
|
'CLKOUT1': [
|
||||||
('LOW_TIME', 6),
|
('LOW_TIME', 6),
|
||||||
('HIGH_TIME', 6),
|
('HIGH_TIME', 6),
|
||||||
# This bit is the output enable bit, which is being detected as a pip
|
('OUTPUT_ENABLE', 1),
|
||||||
# bit, which is roughly correct. Leave this bit as a pip bit.
|
|
||||||
(None, 1),
|
|
||||||
('PHASE_MUX', 3),
|
('PHASE_MUX', 3),
|
||||||
],
|
],
|
||||||
'CLKOUT2': [
|
'CLKOUT2': [
|
||||||
|
|
@ -60,11 +58,20 @@ REGISTER_LAYOUT = {
|
||||||
],
|
],
|
||||||
'POWER_REG': [
|
'POWER_REG': [
|
||||||
('POWER_REG', 16),
|
('POWER_REG', 16),
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BASE_OFFSET = 0x00
|
||||||
REGISTER_MAP = []
|
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
|
# 0x06 - 0x15
|
||||||
for output in ['CLKOUT5', 'CLKOUT0', 'CLKOUT1', 'CLKOUT2', 'CLKOUT3',
|
for output in ['CLKOUT5', 'CLKOUT0', 'CLKOUT1', 'CLKOUT2', 'CLKOUT3',
|
||||||
'CLKOUT4', None, 'CLKFBOUT']:
|
'CLKOUT4', None, 'CLKFBOUT']:
|
||||||
|
|
@ -96,17 +103,24 @@ for _ in range(0x4E - 0x28 - 1):
|
||||||
REGISTER_MAP.append(('FILTREG1', 'FILTREG1'))
|
REGISTER_MAP.append(('FILTREG1', 'FILTREG1'))
|
||||||
REGISTER_MAP.append(('FILTREG2', 'FILTREG2'))
|
REGISTER_MAP.append(('FILTREG2', 'FILTREG2'))
|
||||||
|
|
||||||
|
for _ in range(0x20):
|
||||||
|
REGISTER_MAP.append(None)
|
||||||
|
|
||||||
|
|
||||||
class RegisterAddress(object):
|
class RegisterAddress(object):
|
||||||
def __init__(self, frame_offsets, bit_offset):
|
def __init__(self, frame_offsets, bit_offset):
|
||||||
self.frame_index = 0
|
self.frame_index = 0
|
||||||
self.frame_offsets = frame_offsets
|
self.frame_offsets = frame_offsets
|
||||||
self.bit_offset = bit_offset
|
self.bit_offset = bit_offset
|
||||||
|
self.bits_used = set()
|
||||||
|
|
||||||
def next_bit(self):
|
def next_bit(self, used=True):
|
||||||
output = '{}_{}'.format(
|
output = '{}_{}'.format(
|
||||||
self.frame_offsets[self.frame_index], self.bit_offset)
|
self.frame_offsets[self.frame_index], self.bit_offset)
|
||||||
|
|
||||||
|
if used:
|
||||||
|
self.bits_used.add(output)
|
||||||
|
|
||||||
self.frame_index += 1
|
self.frame_index += 1
|
||||||
if self.frame_index >= len(self.frame_offsets):
|
if self.frame_index >= len(self.frame_offsets):
|
||||||
self.frame_index = 0
|
self.frame_index = 0
|
||||||
|
|
@ -130,6 +144,7 @@ def passthrough_non_register_segbits(seg_in):
|
||||||
base_offset_register = 'CMT_UPPER_T.PLLE2.CLKOUT5_DIVIDE[1]'
|
base_offset_register = 'CMT_UPPER_T.PLLE2.CLKOUT5_DIVIDE[1]'
|
||||||
|
|
||||||
bit_offset = None
|
bit_offset = None
|
||||||
|
in_use = None
|
||||||
with open(seg_in, 'r') as f:
|
with open(seg_in, 'r') as f:
|
||||||
for l in f:
|
for l in f:
|
||||||
if l.startswith(base_offset_register):
|
if l.startswith(base_offset_register):
|
||||||
|
|
@ -140,10 +155,15 @@ def passthrough_non_register_segbits(seg_in):
|
||||||
|
|
||||||
assert frame_offset == 28
|
assert frame_offset == 28
|
||||||
assert bit_index > 3
|
assert bit_index > 3
|
||||||
bit_offset = bit_index - 3
|
bit_offset = bit_index - 3 - 16 * 3
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if 'IN_USE' in l:
|
||||||
|
assert in_use is None
|
||||||
|
in_use = l.strip()
|
||||||
|
continue
|
||||||
|
|
||||||
parts = l.split()
|
parts = l.split()
|
||||||
feature_parts = parts[0].split('.')
|
feature_parts = parts[0].split('.')
|
||||||
|
|
||||||
|
|
@ -177,10 +197,11 @@ def passthrough_non_register_segbits(seg_in):
|
||||||
print(l.strip())
|
print(l.strip())
|
||||||
|
|
||||||
assert bit_offset is not None
|
assert bit_offset is not None
|
||||||
return bit_offset
|
assert in_use is not None
|
||||||
|
return bit_offset, in_use
|
||||||
|
|
||||||
|
|
||||||
def output_registers(bit_offset):
|
def output_registers(bit_offset, in_use):
|
||||||
""" Output segbits for the known PLL register space.
|
""" Output segbits for the known PLL register space.
|
||||||
|
|
||||||
The first bit offset in the register space is required to generate this
|
The first bit offset in the register space is required to generate this
|
||||||
|
|
@ -192,7 +213,7 @@ def output_registers(bit_offset):
|
||||||
for idx, register in enumerate(REGISTER_MAP):
|
for idx, register in enumerate(REGISTER_MAP):
|
||||||
if register is None:
|
if register is None:
|
||||||
for _ in range(16):
|
for _ in range(16):
|
||||||
reg.next_bit()
|
reg.next_bit(used=False)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
layout, register_name = register
|
layout, register_name = register
|
||||||
|
|
@ -209,7 +230,7 @@ def output_registers(bit_offset):
|
||||||
bit_count += 1
|
bit_count += 1
|
||||||
|
|
||||||
if field is None:
|
if field is None:
|
||||||
reg.next_bit()
|
reg.next_bit(used=False)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(
|
print(
|
||||||
|
|
@ -222,7 +243,7 @@ def output_registers(bit_offset):
|
||||||
bit_count += 1
|
bit_count += 1
|
||||||
|
|
||||||
if field is None:
|
if field is None:
|
||||||
reg.next_bit()
|
reg.next_bit(used=False)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(
|
print(
|
||||||
|
|
@ -241,6 +262,11 @@ def output_registers(bit_offset):
|
||||||
'CMT_UPPER_T.PLLE2.{}[{}] {}'.format(
|
'CMT_UPPER_T.PLLE2.{}[{}] {}'.format(
|
||||||
register_name, bit, reg.next_bit()))
|
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():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="")
|
parser = argparse.ArgumentParser(description="")
|
||||||
|
|
@ -249,9 +275,9 @@ def main():
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
bit_offset = passthrough_non_register_segbits(args.seg_in)
|
bit_offset, in_use = passthrough_non_register_segbits(args.seg_in)
|
||||||
|
|
||||||
output_registers(bit_offset)
|
output_registers(bit_offset, in_use)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
export FUZDIR=$(shell pwd)
|
||||||
|
PIP_TYPE?=cmt_top
|
||||||
|
PIPLIST_TCL=$(FUZDIR)/cmt_top_upper_t.tcl
|
||||||
|
TODO_RE=".*"
|
||||||
|
|
||||||
|
MAKETODO_FLAGS=--sides "r_upper_t,l_upper_t" --pip-type ${PIP_TYPE} --seg-type cmt_top --re $(TODO_RE)
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
database: build/segbits_cmt_top_l_upper_t.rdb build/segbits_cmt_top_r_upper_t.rdb
|
||||||
|
${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
|
||||||
|
|
||||||
|
${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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
${XRAY_MASKMERGE} build/mask_cmt_top_l_upper_t.db \
|
||||||
|
$(shell find build -name segdata_cmt_top_l_upper_t.txt)
|
||||||
|
${XRAY_MASKMERGE} build/mask_cmt_top_r_upper_t.db \
|
||||||
|
$(shell find build -name segdata_cmt_top_r_upper_t.txt)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} cmt_top_r_upper_t build/segbits_cmt_top_r_upper_t.db
|
||||||
|
|
||||||
|
pushdb: database
|
||||||
|
${XRAY_MERGEDB} cmt_top_l_upper_t build/segbits_cmt_top_l_upper_t.db
|
||||||
|
${XRAY_MERGEDB} cmt_top_r_upper_t build/segbits_cmt_top_r_upper_t.db
|
||||||
|
|
||||||
|
.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()
|
||||||
Loading…
Reference in New Issue