blob: 2c9363bb2e9873c7d11e52752d76ab6f5ff04166 [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, random
random.seed(int(os.getenv("SEED"), 16))
import json
from prjxray import util
from prjxray import verilog
from prjxray.db import Database
# =============================================================================
def gen_sites():
db = Database(util.get_db_root(), util.get_part())
grid = db.grid()
tile_list = []
for tile_name in sorted(grid.tiles()):
if "IOB33" not in tile_name or "SING" in tile_name:
continue
tile_list.append(tile_name)
get_xy = util.create_xy_fun('[LR]IOB33_')
tile_list.sort(key=get_xy)
for iob_tile_name in tile_list:
iob_gridinfo = grid.gridinfo_at_loc(
grid.loc_of_tilename(iob_tile_name))
iob33s = [k for k, v in iob_gridinfo.sites.items() if v == "IOB33S"][0]
iob33m = [k for k, v in iob_gridinfo.sites.items() if v == "IOB33M"][0]
top_sites = {
"IOB": iob33m,
"ILOGIC": iob33m.replace("IOB", "ILOGIC"),
"IDELAY": iob33m.replace("IOB", "IDELAY"),
}
bot_sites = {
"IOB": iob33s,
"ILOGIC": iob33s.replace("IOB", "ILOGIC"),
"IDELAY": iob33s.replace("IOB", "IDELAY"),
}
yield iob_tile_name, top_sites, bot_sites
def gen_iserdes(loc):
# Site params
params = {
"SITE_LOC": verilog.quote(loc),
"USE_IDELAY": random.randint(0, 1),
"BEL_TYPE": verilog.quote("ISERDESE2"),
"INIT_Q1": random.randint(0, 1),
"INIT_Q2": random.randint(0, 1),
"INIT_Q3": random.randint(0, 1),
"INIT_Q4": random.randint(0, 1),
"SRVAL_Q1": random.randint(0, 1),
"SRVAL_Q2": random.randint(0, 1),
"SRVAL_Q3": random.randint(0, 1),
"SRVAL_Q4": random.randint(0, 1),
"NUM_CE": random.randint(1, 2),
# The following one shows negative correlation (0 - not inverted)
"IS_D_INVERTED": random.randint(0, 1),
# No bits were found for parameters below
"IS_OCLKB_INVERTED": random.randint(0, 1),
"IS_OCLK_INVERTED": random.randint(0, 1),
"IS_CLKDIVP_INVERTED": random.randint(0, 1),
"IS_CLKDIV_INVERTED": random.randint(0, 1),
"IS_CLKB_INVERTED": random.randint(0, 1),
"IS_CLK_INVERTED": random.randint(0, 1),
"DYN_CLKDIV_INV_EN": verilog.quote(random.choice(["TRUE", "FALSE"])),
"DYN_CLK_INV_EN": verilog.quote(random.choice(["TRUE", "FALSE"])),
"IOBDELAY": verilog.quote(
random.choice(["NONE", "IBUF", "IFD", "BOTH"])),
"OFB_USED": verilog.quote(
random.choice(["TRUE"] + ["FALSE"] * 9)), # Force more FALSEs
}
iface_type = random.choice(
["NETWORKING", "OVERSAMPLE", "MEMORY", "MEMORY_DDR3", "MEMORY_QDR"])
data_rate = random.choice(["SDR", "DDR"])
serdes_mode = random.choice(["MASTER", "SLAVE"])
params["INTERFACE_TYPE"] = verilog.quote(iface_type)
params["DATA_RATE"] = verilog.quote(data_rate)
params["SERDES_MODE"] = verilog.quote(serdes_mode)
# Networking mode
if iface_type == "NETWORKING":
data_widths = {
"SDR": [2, 3, 4, 5, 6, 7, 8],
"DDR": [4, 6, 8, 10, 14],
}
params["DATA_WIDTH"] = random.choice(data_widths[data_rate])
# Others
else:
params["DATA_WIDTH"] = 4
if verilog.unquote(params["OFB_USED"]) == "TRUE":
params["IOBDELAY"] = verilog.quote("NONE")
return params
def gen_iddr(loc):
# Site params
params = {
"SITE_LOC":
verilog.quote(loc),
"USE_IDELAY":
random.randint(0, 1),
"BEL_TYPE":
verilog.quote(random.choice(["IDDR", "IDDR_NO_CLK"])),
"INIT_Q1":
random.randint(0, 1),
"INIT_Q2":
random.randint(0, 1),
"SRTYPE":
verilog.quote(random.choice(["ASYNC", "SYNC"])),
"DDR_CLK_EDGE":
verilog.quote(
random.choice(
["OPPOSITE_EDGE", "SAME_EDGE", "SAME_EDGE_PIPELINED"])),
"CE1USED":
random.randint(0, 1),
"SR_MODE":
verilog.quote(random.choice(["NONE", "SET", "RST"])),
"IS_C_INVERTED":
random.randint(0, 1),
"IS_D_INVERTED":
random.randint(0, 1),
}
if params["USE_IDELAY"]:
params["IDELMUX"] = random.randint(0, 1)
params["IFFDELMUX"] = random.randint(0, 1)
else:
params["IDELMUX"] = 0
params["IFFDELMUX"] = 0
return params
def run():
# Get all [LR]IOI3 tiles
tiles = list(gen_sites())
# Header
print("// Tile count: %d" % len(tiles))
print("// Seed: '%s'" % os.getenv("SEED"))
print(
'''
module top (
(* CLOCK_BUFFER_TYPE = "NONE" *)
input wire clk1,
(* CLOCK_BUFFER_TYPE = "NONE" *)
input wire clk2,
input wire ce,
input wire rst,
input wire [{N}:0] di,
output wire [{N}:0] do
);
wire [{N}:0] di_buf;
wire [{N}:0] do_buf;
// IDELAYCTRL
(* KEEP, DONT_TOUCH *)
IDELAYCTRL idelayctrl();
'''.format(**{"N": len(tiles) - 1}))
# LOCes IOBs
data = []
for i, sites in enumerate(tiles):
tile_name = sites[0]
# Use site
if random.randint(0, 19) > 0: # Use more often
# Top sites
if random.randint(0, 1):
this_sites = sites[1]
other_sites = sites[2]
# Bottom sites
else:
this_sites = sites[2]
other_sites = sites[1]
# Generate cell
bel_types = ["IDDR", "ISERDESE2"]
bel_type = bel_types[int(
random.randint(0, 2) > 0)] # ISERDES more often
if bel_type == "ISERDESE2":
params = gen_iserdes(this_sites["ILOGIC"])
if bel_type == "IDDR":
params = gen_iddr(this_sites["ILOGIC"])
params["IDELAY_LOC"] = verilog.quote(this_sites["IDELAY"])
params["IS_USED"] = 1
# Instantiate the cell
print('')
print('// This : ' + " ".join(this_sites.values()))
print('// Other: ' + " ".join(other_sites.values()))
print('(* LOC="%s", KEEP, DONT_TOUCH *)' % this_sites["IOB"])
print('IBUF ibuf_%03d (.I(di[%3d]), .O(di_buf[%3d]));' % (i, i, i))
print('(* LOC="%s", KEEP, DONT_TOUCH *)' % other_sites["IOB"])
print('OBUF obuf_%03d (.I(do_buf[%3d]), .O(do[%3d]));' % (i, i, i))
clk1_conn = random.choice(["clk1", ""])
param_str = ",".join(".%s(%s)" % (k, v) for k, v in params.items())
print(
'ilogic_single #(%s) ilogic_%03d (.clk1(%s), .clk2(clk2), .ce(ce), .rst(rst), .I(di_buf[%3d]), .O(do_buf[%3d]));'
% (param_str, i, clk1_conn, i, i))
params["CHAINED"] = 0
params["TILE_NAME"] = tile_name
# Params for the second site
other_params = {
"TILE_NAME": tile_name,
"SITE_LOC": verilog.quote(other_sites["ILOGIC"]),
"IDELAY_LOC": verilog.quote(other_sites["IDELAY"]),
"IS_USED": 0,
}
# Append to data list
data.append([params, other_params])
# Don't use sites
else:
params_list = [
{
"TILE_NAME": tile_name,
"SITE_LOC": verilog.quote(sites[1]["ILOGIC"]),
"IDELAY_LOC": verilog.quote(sites[1]["IDELAY"]),
"IS_USED": 0,
},
{
"TILE_NAME": tile_name,
"SITE_LOC": verilog.quote(sites[2]["ILOGIC"]),
"IDELAY_LOC": verilog.quote(sites[2]["IDELAY"]),
"IS_USED": 0,
}
]
data.append(params_list)
# Store params
with open("params.json", "w") as fp:
json.dump(data, fp, sort_keys=True, indent=1)
print(
'''
endmodule
(* KEEP, DONT_TOUCH *)
module ilogic_single(
input wire clk1,
input wire clk2,
input wire ce,
input wire rst,
input wire I,
output wire O,
input wire [1:0] shiftin,
output wire [1:0] shiftout
);
parameter SITE_LOC = "";
parameter IS_USED = 1;
parameter BEL_TYPE = "ISERDESE2";
parameter IDELAY_LOC = "";
parameter USE_IDELAY = 0;
parameter IDELMUX = 0;
parameter IFFDELMUX = 0;
parameter INTERFACE_TYPE = "NETWORKING";
parameter DATA_RATE = "DDR";
parameter DATA_WIDTH = 4;
parameter SERDES_MODE = "MASTER";
parameter NUM_CE = 2;
parameter INIT_Q1 = 0;
parameter INIT_Q2 = 0;
parameter INIT_Q3 = 0;
parameter INIT_Q4 = 0;
parameter SRVAL_Q1 = 0;
parameter SRVAL_Q2 = 0;
parameter SRVAL_Q3 = 0;
parameter SRVAL_Q4 = 0;
parameter IS_D_INVERTED = 0;
parameter IS_OCLK_INVERTED = 0;
parameter IS_OCLKB_INVERTED = 0;
parameter IS_CLK_INVERTED = 0;
parameter IS_CLKB_INVERTED = 0;
parameter IS_CLKDIV_INVERTED = 0;
parameter IS_CLKDIVP_INVERTED = 0;
parameter DYN_CLKDIV_INV_EN = "FALSE";
parameter DYN_CLK_INV_EN = "FALSE";
parameter IOBDELAY = "NONE";
parameter OFB_USED = "FALSE";
parameter DDR_CLK_EDGE = "OPPOSITE_EDGE";
parameter SRTYPE = "ASYNC";
parameter CE1USED = 0;
parameter SR_MODE = "NONE";
parameter IS_C_INVERTED = 0;
wire [8:0] x;
wire ddly;
(* KEEP, DONT_TOUCH *)
generate if (IS_USED && USE_IDELAY) begin
// IDELAY
(* LOC=IDELAY_LOC, KEEP, DONT_TOUCH *)
IDELAYE2 idelay
(
.C(clk),
.REGRST(),
.LD(),
.CE(),
.INC(),
.CINVCTRL(),
.CNTVALUEIN(),
.IDATAIN(I),
.DATAIN(),
.LDPIPEEN(),
.DATAOUT(ddly),
.CNTVALUEOUT()
);
end else begin
assign ddly = 0;
end endgenerate
(* KEEP, DONT_TOUCH *)
generate if (IS_USED && BEL_TYPE == "ISERDESE2") begin
// ISERDES
(* LOC=SITE_LOC, KEEP, DONT_TOUCH *)
ISERDESE2 #
(
.INTERFACE_TYPE(INTERFACE_TYPE),
.DATA_RATE(DATA_RATE),
.DATA_WIDTH(DATA_WIDTH),
.SERDES_MODE(SERDES_MODE),
.NUM_CE(NUM_CE),
.IS_D_INVERTED(IS_D_INVERTED),
.IS_OCLK_INVERTED(IS_OCLK_INVERTED),
.IS_OCLKB_INVERTED(IS_OCLKB_INVERTED),
.IS_CLK_INVERTED(IS_CLK_INVERTED),
.IS_CLKB_INVERTED(IS_CLKB_INVERTED),
.IS_CLKDIV_INVERTED(IS_CLKDIV_INVERTED),
.IS_CLKDIVP_INVERTED(IS_CLKDIVP_INVERTED),
.INIT_Q1(INIT_Q1),
.INIT_Q2(INIT_Q2),
.INIT_Q3(INIT_Q3),
.INIT_Q4(INIT_Q4),
.SRVAL_Q1(SRVAL_Q1),
.SRVAL_Q2(SRVAL_Q2),
.SRVAL_Q3(SRVAL_Q3),
.SRVAL_Q4(SRVAL_Q4),
.DYN_CLKDIV_INV_EN(DYN_CLKDIV_INV_EN),
.DYN_CLK_INV_EN(DYN_CLK_INV_EN),
.IOBDELAY(IOBDELAY),
.OFB_USED(OFB_USED)
)
isedres
(
.D(I),
.DDLY(),
.OFB(),
//.TFB(),
.CE1(),
.CE2(),
.DYNCLKSEL(),
.CLK(clk1),
.CLKB(clk2),
.OCLK(),
.OCLKB(),
.DYNCLKDIVSEL(),
.CLKDIV(),
.CLKDIVP(),
.RST(),
.BITSLIP(),
.O(x[8]),
.Q1(x[0]),
.Q2(x[1]),
.Q3(x[2]),
.Q4(x[3]),
.Q5(x[4]),
.Q6(x[5]),
.Q7(x[6]),
.Q8(x[7]),
.SHIFTIN1(shiftin[0]),
.SHIFTIN2(shiftin[1]),
.SHIFTOUT1(shiftout[0]),
.SHIFTOUT2(shiftout[1])
);
end else if (IS_USED && BEL_TYPE == "IDDR") begin
// IDDR
(* LOC=SITE_LOC, KEEP, DONT_TOUCH *)
IDDR #
(
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.DDR_CLK_EDGE(DDR_CLK_EDGE),
.INIT_Q1(INIT_Q1),
.INIT_Q2(INIT_Q2),
.SRTYPE(SRTYPE)
)
iddr
(
.C(clk1),
.CE( (CE1USED) ? ce : 1'hx ),
.D( (IFFDELMUX) ? ddly : I ),
.S( (SR_MODE == "SET") ? rst : 1'd0 ),
.R( (SR_MODE == "RST") ? rst : 1'd0 ),
.Q1(x[0]),
.Q2(x[1])
);
assign x[8] = (IDELMUX) ? ddly : I;
assign x[7:2] = 0;
end else if (IS_USED && BEL_TYPE == "IDDR_NO_CLK") begin
// IDDR
(* LOC=SITE_LOC, KEEP, DONT_TOUCH *)
IDDR #
(
.IS_C_INVERTED(IS_C_INVERTED),
.IS_D_INVERTED(IS_D_INVERTED),
.DDR_CLK_EDGE(DDR_CLK_EDGE),
.INIT_Q1(INIT_Q1),
.INIT_Q2(INIT_Q2),
.SRTYPE(SRTYPE)
)
iddr
(
.C(),
.CE( (CE1USED) ? ce : 1'hx ),
.D( (IFFDELMUX) ? ddly : I ),
.S( (SR_MODE == "SET") ? rst : 1'd0 ),
.R( (SR_MODE == "RST") ? rst : 1'd0 ),
.Q1(x[0]),
.Q2(x[1])
);
assign x[8] = (IDELMUX) ? ddly : I;
assign x[7:2] = 0;
end else begin
assign x[0] = I;
assign x[1] = I;
assign x[2] = I;
assign x[3] = I;
assign x[4] = I;
assign x[5] = I;
assign x[6] = I;
assign x[7] = I;
assign x[8] = I;
end endgenerate
// Output
assign O = |x;
endmodule
''')
run()