#!/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()