blob: 3d866543f4b52ffc0b2368d17931c37d4f3bd99a [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017-2020 The Project X-Ray Authors.
#
# Use of this source code is governed by a ISC-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/ISC
#
# SPDX-License-Identifier: ISC
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray import verilog
from prjxray.db import Database
import json
def find_hclk_ref_wires_for_mmcm(grid, loc):
tilename = grid.tilename_at_loc((loc[0], loc[1] - 17))
gridinfo = grid.gridinfo_at_tilename(tilename)
assert gridinfo.tile_type in ['HCLK_CMT_L', 'HCLK_CMT']
# HCLK_CMT_MUX_OUT_FREQ_REF[0-3]
wires = []
for idx in range(4):
wires.append('{}/HCLK_CMT_MUX_OUT_FREQ_REF{}'.format(tilename, idx))
return wires
def gen_sites():
db = Database(util.get_db_root(), util.get_part())
grid = db.grid()
for tile_name in sorted(grid.tiles()):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
tile_type = tile_name.rsplit("_", 1)[0]
for site_name, site_type in gridinfo.sites.items():
if site_type in ['MMCME2_ADV']:
hclk_wires = find_hclk_ref_wires_for_mmcm(grid, loc)
yield tile_name, tile_type, site_name, hclk_wires
def gen_true_false(p):
if random.random() <= p:
return verilog.quote("TRUE")
else:
return verilog.quote("FALSE")
def main():
sites = sorted(list(gen_sites()))
max_sites = len(sites)
f = open('params.jl', 'w')
f.write('module,loc,params\n')
routes_file = open('routes.txt', 'w')
print(
"""
module top(
input [{N}:0] clkin1,
input [{N}:0] clkin2,
input [{N}:0] clkfb,
input [{N}:0] dclk
);
(* KEEP, DONT_TOUCH *)
LUT1 dummy();
""".format(N=max_sites - 1))
for i, (tile_name, tile_type, site,
hclk_wires) in enumerate(sorted(gen_sites())):
params = {
"site":
site,
'active':
random.random() > .2,
"clkin1_conn":
random.choice(
("clkfbout_mult_BUFG_" + site, "clkin1[{}]".format(i), "")),
"clkin2_conn":
random.choice(
("clkfbout_mult_BUFG_" + site, "clkin2[{}]".format(i), "")),
"dclk_conn":
random.choice((
"0",
"dclk[{}]".format(i),
)),
"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),
"IS_PSEN_INVERTED":
random.randint(0, 1),
"IS_PSINCDEC_INVERTED":
random.randint(0, 1),
"CLKFBOUT_MULT_F":
random.randint(2, 4),
"CLKOUT0_DIVIDE_F":
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),
"CLKOUT6_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',
))),
"SS_EN":
gen_true_false(0.15),
}
# SS_EN requires BANDWIDTH to be LOW
if verilog.unquote(params["SS_EN"]) == "TRUE":
params["BANDWIDTH"] = verilog.quote("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(
("", "clkfb[{}]".format(i), "clkfbout_mult_BUFG_" + site))
def get_clkin_wires(idx):
wires = [
"{tile}_CLKIN{idx}", "{tile}_FREQ_BB0", "{tile}_FREQ_BB1",
"{tile}_FREQ_BB2", "{tile}_FREQ_BB3", "{tile}_CLK_IN{idx}_INT"
"{tile}_CLK_IN{idx}_HCLK"
]
return [
tile_name + "/" + w.format(tile=tile_type, idx=idx)
for w in wires
]
params['clkin1_route'] = random.choice(get_clkin_wires(1) + hclk_wires)
params['clkin2_route'] = random.choice(get_clkin_wires(2) + hclk_wires)
params['clkfbin_route'] = random.choice(
(
"{}_CLKFBOUT2IN",
"{}_FREQ_BB0",
"{}_FREQ_BB1",
"{}_FREQ_BB2",
"{}_FREQ_BB3",
"{}_CLK_IN3_INT",
"{}_CLK_IN3_HCLK",
)).format(tile_type)
f.write('%s\n' % (json.dumps(params)))
def make_ibuf_net(net):
p = net.find('[')
return net[:p] + '_IBUF' + net[p:]
if params['clkin1_conn'] != "":
net = params['clkin1_conn']
if "[" in net and "]" in net:
net = make_ibuf_net(net)
wire = params['clkin1_route']
routes_file.write('{} {}\n'.format(net, wire))
if params['clkin2_conn'] != "":
net = params['clkin2_conn']
if "[" in net and "]" in net:
net = make_ibuf_net(net)
wire = params['clkin2_route']
routes_file.write('{} {}\n'.format(net, wire))
if params['clkfbin_conn'] != "" and\
params['clkfbin_conn'] != ("clkfbout_mult_BUFG_" + site):
net = params['clkfbin_conn']
if "[" in net and "]" in net:
net = make_ibuf_net(net)
wire = '{}/{}'.format(tile_name, params['clkfbin_route'])
routes_file.write('{} {}\n'.format(net, wire))
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};
wire clkout6_{site};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
MMCME2_ADV #(
.IS_RST_INVERTED({IS_RST_INVERTED}),
.IS_PWRDWN_INVERTED({IS_PWRDWN_INVERTED}),
.IS_CLKINSEL_INVERTED({IS_CLKINSEL_INVERTED}),
.IS_PSEN_INVERTED({IS_PSEN_INVERTED}),
.IS_PSINCDEC_INVERTED({IS_PSINCDEC_INVERTED}),
.CLKOUT0_DIVIDE_F({CLKOUT0_DIVIDE_F}),
.CLKOUT1_DIVIDE({CLKOUT1_DIVIDE}),
.CLKOUT2_DIVIDE({CLKOUT2_DIVIDE}),
.CLKOUT3_DIVIDE({CLKOUT3_DIVIDE}),
.CLKOUT4_DIVIDE({CLKOUT4_DIVIDE}),
.CLKOUT5_DIVIDE({CLKOUT5_DIVIDE}),
.CLKOUT6_DIVIDE({CLKOUT6_DIVIDE}),
.CLKFBOUT_MULT_F({CLKFBOUT_MULT_F}),
.DIVCLK_DIVIDE({DIVCLK_DIVIDE}),
.STARTUP_WAIT({STARTUP_WAIT}),
.CLKOUT0_DUTY_CYCLE({CLKOUT0_DUTY_CYCLE}),
.COMPENSATION({COMPENSATION}),
.BANDWIDTH({BANDWIDTH}),
.SS_EN({SS_EN}),
.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}),
.CLKOUT6(clkout6_{site}),
.DRDY(),
.LOCKED(),
.DO(),
.CLKFBIN({clkfbin_conn}),
.CLKIN1({clkin1_conn}),
.CLKIN2({clkin2_conn}),
.CLKINSEL(),
.DCLK({dclk_conn}),
.DEN({den_conn}),
.DWE({dwe_conn}),
.PWRDWN(),
.RST(),
.DI(),
.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})
);
""".format(**params))
disabled_clkout = random.randint(0, 7)
for clk in range(0, 7):
if clk == disabled_clkout:
continue
print(
"""
(* KEEP, DONT_TOUCH *)
FDRE reg_clkout{clk}_{site} (
.C(clkout{clk}_{site})
);
""".format(clk=clk, site=params['site']))
print('endmodule')
f.close()
if __name__ == "__main__":
main()