mirror of https://github.com/openXC7/prjxray.git
344 lines
9.9 KiB
Python
344 lines
9.9 KiB
Python
#!/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()
|