#!/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 re import json from prjxray import util 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)) # Find IOI tile adjacent to IOB for suffix in ["IOI3", "IOI3_TBYTESRC", "IOI3_TBYTETERM"]: try: ioi_tile_name = iob_tile_name.replace("IOB33", suffix) ioi_gridinfo = grid.gridinfo_at_loc( grid.loc_of_tilename(ioi_tile_name)) break except KeyError: pass 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] idelay_s = iob33s.replace("IOB", "IDELAY") idelay_m = iob33m.replace("IOB", "IDELAY") yield iob33m, idelay_m, iob33s, idelay_s def run(): # Get all [LR]IOI3 tiles tiles = list(gen_sites()) # Header print("// Tile count: %d" % len(tiles)) print("// Seed: '%s'" % os.getenv("SEED")) ninputs = 0 di_idx = [] for i, sites in enumerate(tiles): if random.randint(0, 1): di_idx.append(ninputs) ninputs += 1 else: di_idx.append(None) print( ''' module top ( (* CLOCK_BUFFER_TYPE = "NONE" *) input wire clk, input wire [{N}:0] di ); wire clk_buf = clk; wire [{N}:0] di_buf; '''.format(N=ninputs - 1)) # LOCes IOBs data = [] for i, (sites, ibuf_idx) in enumerate(zip(tiles, di_idx)): if random.randint(0, 1): iob_i = sites[0] iob_o = sites[2] idelay = sites[1] other_idelay = sites[3] else: iob_i = sites[2] iob_o = sites[0] idelay = sites[3] other_idelay = sites[1] use_ibuf = ibuf_idx is not None DELAY_SRC = random.choice(["IDATAIN", "DATAIN"]) if not use_ibuf: DELAY_SRC = 'DATAIN' params = { "LOC": "\"" + idelay + "\"", "IDELAY_TYPE": "\"" + random.choice( ["FIXED", "VARIABLE", "VAR_LOAD", "VAR_LOAD_PIPE"]) + "\"", "IDELAY_VALUE": random.randint(0, 31), "DELAY_SRC": "\"" + DELAY_SRC + "\"", "HIGH_PERFORMANCE_MODE": "\"" + random.choice(["TRUE", "FALSE"]) + "\"", "CINVCTRL_SEL": "\"" + random.choice(["TRUE", "FALSE"]) + "\"", "PIPE_SEL": "\"" + random.choice(["TRUE", "FALSE"]) + "\"", "IS_C_INVERTED": random.randint(0, 1), "IS_DATAIN_INVERTED": random.randint(0, 1), "IS_IDATAIN_INVERTED": random.randint(0, 1), } if params["IDELAY_TYPE"] != "\"VAR_LOAD_PIPE\"": params["PIPE_SEL"] = "\"FALSE\"" # The datasheet says that for these two modes the delay is set to 0 if params["IDELAY_TYPE"] == "\"VAR_LOAD\"": params["IDELAY_VALUE"] = 0 if params["IDELAY_TYPE"] == "\"VAR_LOAD_PIPE\"": params["IDELAY_VALUE"] = 0 if params["IDELAY_TYPE"] == "\"FIXED\"": params["IS_C_INVERTED"] = 0 param_str = ",".join(".%s(%s)" % (k, v) for k, v in params.items()) if use_ibuf: print('') print('(* LOC="%s", KEEP, DONT_TOUCH *)' % iob_i) print( 'IBUF ibuf_%03d (.I(di[%3d]), .O(di_buf[%3d]));' % (ibuf_idx, ibuf_idx, ibuf_idx)) print( 'mod #(%s) mod_%03d (.clk(clk_buf), .I(di_buf[%3d]));' % (param_str, i, ibuf_idx)) else: print('mod #(%s) mod_%03d (.clk(clk_buf), .I());' % (param_str, i)) params['IBUF_IN_USE'] = use_ibuf params["IDELAY_IN_USE"] = idelay params["IDELAY_NOT_IN_USE"] = other_idelay data.append(params) # Store params with open("params.json", "w") as fp: json.dump(data, fp, sort_keys=True, indent=1) print( ''' // IDELAYCTRL (* KEEP, DONT_TOUCH *) IDELAYCTRL idelayctrl(); endmodule (* KEEP, DONT_TOUCH *) module mod( input wire clk, input wire I ); parameter LOC = ""; parameter IDELAY_TYPE = "FIXED"; parameter IDELAY_VALUE = 0; parameter DELAY_SRC = "IDATAIN"; parameter HIGH_PERFORMANCE_MODE = "TRUE"; parameter SIGNAL_PATTERN = "DATA"; parameter CINVCTRL_SEL = "FALSE"; parameter PIPE_SEL = "FALSE"; parameter IS_C_INVERTED = 0; parameter IS_DATAIN_INVERTED = 0; parameter IS_IDATAIN_INVERTED = 0; wire x; wire lut; (* KEEP, DONT_TOUCH *) LUT2 l( .O(lut) ); // IDELAY (* LOC=LOC, KEEP, DONT_TOUCH *) IDELAYE2 #( .IDELAY_TYPE(IDELAY_TYPE), .IDELAY_VALUE(IDELAY_VALUE), .DELAY_SRC(DELAY_SRC), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE), .SIGNAL_PATTERN(SIGNAL_PATTERN), .CINVCTRL_SEL(CINVCTRL_SEL), .PIPE_SEL(PIPE_SEL), .IS_C_INVERTED(IS_C_INVERTED), .IS_DATAIN_INVERTED(IS_DATAIN_INVERTED), .IS_IDATAIN_INVERTED(IS_IDATAIN_INVERTED) ) idelay ( .C(clk), .REGRST(), .LD(), .CE(), .INC(), .CINVCTRL(), .CNTVALUEIN(), .IDATAIN(I), .DATAIN(lut), .LDPIPEEN(), .DATAOUT(x), .CNTVALUEOUT() ); endmodule ''') run()