|  | #!/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 json | 
|  |  | 
|  | from prjxray.segmaker import Segmaker | 
|  | from prjxray import util | 
|  | from prjxray import verilog | 
|  |  | 
|  | iface_types = [ | 
|  | "NETWORKING", "OVERSAMPLE", "MEMORY", "MEMORY_DDR3", "MEMORY_QDR" | 
|  | ] | 
|  |  | 
|  | data_rates = ["SDR", "DDR"] | 
|  |  | 
|  | data_widths = { | 
|  | "SDR": [2, 3, 4, 5, 6, 7, 8], | 
|  | "DDR": [4, 6, 8, 10, 14], | 
|  | } | 
|  |  | 
|  |  | 
|  | def run(): | 
|  |  | 
|  | segmk = Segmaker("design.bits") | 
|  |  | 
|  | # Load tags | 
|  | with open("params.json", "r") as fp: | 
|  | data = json.load(fp) | 
|  |  | 
|  | loc_to_tile_site_map = {} | 
|  |  | 
|  | # Output tags | 
|  | for param_list in data: | 
|  | for params in param_list: | 
|  | loc = verilog.unquote(params["SITE_LOC"]) | 
|  |  | 
|  | get_xy = util.create_xy_fun('IOB_') | 
|  | x, y = get_xy(loc.replace("ILOGIC", "IOB")) | 
|  |  | 
|  | loc_to_tile_site_map[loc] = params["TILE_NAME"] + ".IOB_Y%d" % ( | 
|  | y % 2) | 
|  |  | 
|  | # Site not used at all | 
|  | if not params["IS_USED"]: | 
|  |  | 
|  | segmk.add_site_tag(loc, "ISERDES.SHIFTOUT_USED", 0) | 
|  |  | 
|  | segmk.add_site_tag(loc, "IDDR_OR_ISERDES.IN_USE", 0) | 
|  | segmk.add_site_tag(loc, "ISERDES.IN_USE", 0) | 
|  | segmk.add_site_tag(loc, "IDDR.IN_USE", 0) | 
|  |  | 
|  | segmk.add_site_tag(loc, "ISERDES.MODE.MASTER", 0) | 
|  | segmk.add_site_tag(loc, "ISERDES.MODE.SLAVE", 0) | 
|  |  | 
|  | for i in iface_types: | 
|  | if i == "NETWORKING": | 
|  | for j in data_rates: | 
|  | for k in data_widths[j]: | 
|  | tag = "ISERDES.%s.%s.W%s" % (i, j, k) | 
|  | segmk.add_site_tag(loc, tag, 0) | 
|  | else: | 
|  | segmk.add_site_tag(loc, "ISERDES.%s.DDR.W4" % i, 0) | 
|  |  | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N1", 0) | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N2", 0) | 
|  |  | 
|  | for i in range(1, 4 + 1): | 
|  | segmk.add_site_tag(loc, "IFF.ZINIT_Q%d" % i, 0) | 
|  |  | 
|  | for i in range(1, 4 + 1): | 
|  | segmk.add_site_tag(loc, "IFF.ZSRVAL_Q%d" % i, 0) | 
|  |  | 
|  | #            segmk.add_site_tag(loc, "ISERDES.IS_CLKB_INVERTED", 0) | 
|  | #            segmk.add_site_tag(loc, "ISERDES.IS_CLK_INVERTED", 1) | 
|  |  | 
|  | segmk.add_site_tag(loc, "ISERDES.DYN_CLKDIV_INV_EN", 0) | 
|  | segmk.add_site_tag(loc, "ISERDES.DYN_CLK_INV_EN", 0) | 
|  |  | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P1", 1) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P1", 1) | 
|  |  | 
|  | segmk.add_site_tag(loc, "ISERDES.OFB_USED", 0) | 
|  |  | 
|  | # Site used as ISERDESE2 | 
|  | elif verilog.unquote(params["BEL_TYPE"]) == "ISERDESE2": | 
|  |  | 
|  | segmk.add_site_tag(loc, "IDDR_OR_ISERDES.IN_USE", 1) | 
|  | segmk.add_site_tag(loc, "ISERDES.IN_USE", 1) | 
|  |  | 
|  | if "SHIFTOUT_USED" in params: | 
|  | if params["CHAINED"]: | 
|  | value = params["SHIFTOUT_USED"] | 
|  | segmk.add_site_tag(loc, "ISERDES.SHIFTOUT_USED", value) | 
|  |  | 
|  | if "SERDES_MODE" in params: | 
|  | value = verilog.unquote(params["SERDES_MODE"]) | 
|  | if value == "MASTER": | 
|  | segmk.add_site_tag(loc, "ISERDES.MODE.MASTER", 1) | 
|  | segmk.add_site_tag(loc, "ISERDES.MODE.SLAVE", 0) | 
|  | if value == "SLAVE": | 
|  | segmk.add_site_tag(loc, "ISERDES.MODE.MASTER", 0) | 
|  | segmk.add_site_tag(loc, "ISERDES.MODE.SLAVE", 1) | 
|  |  | 
|  | iface_type = verilog.unquote(params["INTERFACE_TYPE"]) | 
|  | data_rate = verilog.unquote(params["DATA_RATE"]) | 
|  | data_width = int(params["DATA_WIDTH"]) | 
|  |  | 
|  | for i in iface_types: | 
|  | if i == "NETWORKING": | 
|  | for j in data_rates: | 
|  | for k in data_widths[j]: | 
|  | tag = "ISERDES.%s.%s.W%s" % (i, j, k) | 
|  |  | 
|  | if i == iface_type: | 
|  | if j == data_rate: | 
|  | if k == data_width: | 
|  | segmk.add_site_tag(loc, tag, 1) | 
|  | else: | 
|  | if i == iface_type: | 
|  | segmk.add_site_tag(loc, "ISERDES.%s.DDR.W4" % i, 1) | 
|  |  | 
|  | if "NUM_CE" in params: | 
|  | value = params["NUM_CE"] | 
|  | if value == 1: | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N1", 1) | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N2", 0) | 
|  | if value == 2: | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N1", 0) | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N2", 1) | 
|  |  | 
|  | for i in range(1, 4 + 1): | 
|  | if ("INIT_Q%d" % i) in params: | 
|  | segmk.add_site_tag( | 
|  | loc, "IFF.ZINIT_Q%d" % i, | 
|  | not params["INIT_Q%d" % i]) | 
|  |  | 
|  | for i in range(1, 4 + 1): | 
|  | if ("SRVAL_Q%d" % i) in params: | 
|  | segmk.add_site_tag( | 
|  | loc, "IFF.ZSRVAL_Q%d" % i, | 
|  | not params["SRVAL_Q%d" % i]) | 
|  |  | 
|  | for inv in ["CLK", "CLKB", "OCLK", "OCLKB", "CLKDIV", | 
|  | "CLKDIVP"]: | 
|  | if "IS_{}_INVERTED".format(inv) in params: | 
|  | segmk.add_site_tag( | 
|  | loc, "ISERDES.INV_{}".format(inv), | 
|  | params["IS_{}_INVERTED".format(inv)]) | 
|  | segmk.add_site_tag( | 
|  | loc, "ISERDES.ZINV_{}".format(inv), | 
|  | not params["IS_{}_INVERTED".format(inv)]) | 
|  |  | 
|  | if "DYN_CLKDIV_INV_EN" in params: | 
|  | value = verilog.unquote(params["DYN_CLKDIV_INV_EN"]) | 
|  | segmk.add_site_tag( | 
|  | loc, "ISERDES.DYN_CLKDIV_INV_EN", int(value == "TRUE")) | 
|  | if "DYN_CLK_INV_EN" in params: | 
|  | value = verilog.unquote(params["DYN_CLK_INV_EN"]) | 
|  | segmk.add_site_tag( | 
|  | loc, "ISERDES.DYN_CLK_INV_EN", int(value == "TRUE")) | 
|  |  | 
|  | # This parameter actually controls muxes used both in ILOGIC and | 
|  | # ISERDES mode. | 
|  | if "IOBDELAY" in params: | 
|  | value = verilog.unquote(params["IOBDELAY"]) | 
|  | if value == "NONE": | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P1", 1) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P1", 1) | 
|  | if value == "IBUF": | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P1", 1) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P0", 1) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P1", 0) | 
|  | if value == "IFD": | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P0", 1) | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P1", 0) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P1", 1) | 
|  | if value == "BOTH": | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P0", 1) | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P1", 0) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P0", 1) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P1", 0) | 
|  |  | 
|  | if "OFB_USED" in params: | 
|  | value = verilog.unquote(params["OFB_USED"]) | 
|  | segmk.add_site_tag( | 
|  | loc, "ISERDES.OFB_USED", int(value == "TRUE")) | 
|  |  | 
|  | # Site used as IDDR | 
|  | elif verilog.unquote(params["BEL_TYPE"]) in ["IDDR", | 
|  | "IDDR_NO_CLK"]: | 
|  | segmk.add_site_tag(loc, "IDDR_OR_ISERDES.IN_USE", 1) | 
|  | segmk.add_site_tag(loc, "IDDR.IN_USE", 1) | 
|  | segmk.add_site_tag(loc, "ISERDES.IN_USE", 0) | 
|  |  | 
|  | if "DDR_CLK_EDGE" in params: | 
|  | value = verilog.unquote(params["DDR_CLK_EDGE"]) | 
|  | segmk.add_site_tag( | 
|  | loc, "IFF.DDR_CLK_EDGE.OPPOSITE_EDGE", | 
|  | int(value == "OPPOSITE_EDGE")) | 
|  | segmk.add_site_tag( | 
|  | loc, "IFF.DDR_CLK_EDGE.SAME_EDGE", | 
|  | int(value == "SAME_EDGE")) | 
|  | segmk.add_site_tag( | 
|  | loc, "IFF.DDR_CLK_EDGE.SAME_EDGE_PIPELINED", | 
|  | int(value == "SAME_EDGE_PIPELINED")) | 
|  |  | 
|  | if "SRTYPE" in params: | 
|  | value = verilog.unquote(params["SRTYPE"]) | 
|  | if value == "ASYNC": | 
|  | segmk.add_site_tag(loc, "IFF.SRTYPE.ASYNC", 1) | 
|  | segmk.add_site_tag(loc, "IFF.SRTYPE.SYNC", 0) | 
|  | if value == "SYNC": | 
|  | segmk.add_site_tag(loc, "IFF.SRTYPE.ASYNC", 0) | 
|  | segmk.add_site_tag(loc, "IFF.SRTYPE.SYNC", 1) | 
|  |  | 
|  | if "IDELMUX" in params: | 
|  | if params["IDELMUX"] == 1: | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P0", 1) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P1", 0) | 
|  | else: | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IDELMUXE3.P1", 1) | 
|  |  | 
|  | if "IFFDELMUX" in params: | 
|  | if params["IFFDELMUX"] == 1: | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P0", 1) | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P1", 0) | 
|  | else: | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P0", 0) | 
|  | segmk.add_site_tag(loc, "IFFDELMUXE3.P1", 1) | 
|  |  | 
|  | for inv in ["C", "D"]: | 
|  | if "IS_{}_INVERTED".format(inv) in params: | 
|  | segmk.add_site_tag( | 
|  | loc, "INV_{}".format(inv), | 
|  | params["IS_{}_INVERTED".format(inv)]) | 
|  | segmk.add_site_tag( | 
|  | loc, "ZINV_{}".format(inv), | 
|  | not params["IS_{}_INVERTED".format(inv)]) | 
|  |  | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N1", 1) | 
|  | segmk.add_site_tag(loc, "ISERDES.NUM_CE.N2", 0) | 
|  |  | 
|  | # Should not happen | 
|  | else: | 
|  | print("Unknown BEL_TYPE '{}'".format(params["BEL_TYPE"])) | 
|  | exit(-1) | 
|  |  | 
|  | # Write segments and tags for later check | 
|  | def_tags = {t: 0 for d in segmk.site_tags.values() for t in d.keys()} | 
|  |  | 
|  | with open("tags.json", "w") as fp: | 
|  | tags = {} | 
|  | for l, d in segmk.site_tags.items(): | 
|  | d1 = dict(def_tags) | 
|  | d1.update({k: int(v) for k, v in d.items()}) | 
|  | tags[loc_to_tile_site_map[l]] = d1 | 
|  |  | 
|  | json.dump(tags, fp, sort_keys=True, indent=1) | 
|  |  | 
|  | def bitfilter(frame_idx, bit_idx): | 
|  | if frame_idx < 26 or frame_idx > 29: | 
|  | return False | 
|  | return True | 
|  |  | 
|  | segmk.compile(bitfilter=bitfilter) | 
|  | segmk.write() | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | run() |