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