063-gtx-common-conf gives first plausible results

Signed-off-by: Hans Baier <foss@hans-baier.de>
This commit is contained in:
Hans Baier 2024-10-25 09:00:44 +07:00
parent 26ccc8a038
commit 51a0b43919
11 changed files with 662 additions and 1 deletions

View File

@ -105,7 +105,7 @@ def add_tile_bits(
assert offset <= 100, (tile_name, offset)
# Few rare cases at X=0 for double width tiles split in half => small negative offset
assert offset >= 0 or "IOB" in tile_name, (
assert offset >= 0 or "IOB" in tile_name or "GTX_INT_INTERFACE" in tile_name, (
tile_name, hex(baseaddr), offset)
assert 1 <= words <= 101, words
assert offset + words <= 101, (

View File

@ -0,0 +1,67 @@
# 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
SHELL = bash
N ?= 20
BUILD_DIR = build_${XRAY_PART}
SPECIMENS := $(addprefix ${BUILD_DIR}/specimen_,$(shell seq -f '%03.0f' $(N)))
SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))
FUZDIR ?= ${PWD}
CELLS_DATA_DIR = ${XRAY_FAMILY_DIR}/cells_data
all: database
# generate.sh / top_generate.sh call make, hence the command must
# have a + before it.
$(SPECIMENS_OK): $(SPECIMENS_DEPS)
mkdir -p ${BUILD_DIR}
bash ${XRAY_DIR}/utils/top_generate.sh $(subst /OK,,$@)
run:
$(MAKE) clean
$(MAKE) database
$(MAKE) pushdb
touch run.${XRAY_PART}.ok
clean:
rm -rf ${BUILD_DIR} run.${XRAY_PART}.ok
.PHONY: all run clean
# These are pins that are hard to parse as a regexp given that the port name ends with a number, which is misinterpreted
# as the index in the port bus
SPECIAL_PINS = PLLRSVD1,PLLRSVD2,GTREFCLK0,GTREFCLK1,GTGREFCLK0,GTGREFCLK1,GTEASTREFCLK0,GTEASTREFCLK1,GTWESTREFCLK0,GTWESTREFCLK1,REFCLKOUTMONITOR0,REFCLKOUTMONITOR1
$(BUILD_DIR)/gtxe2_common_ports.csv: generate_ports.tcl
env FILE_NAME=$(BUILD_DIR)/gtxe2_common_pins.csv ${XRAY_VIVADO} -mode batch -source generate_ports.tcl
$(BUILD_DIR)/gtxe2_common_ports.json: $(BUILD_DIR)/gtxe2_common_ports.csv
python3 ${XRAY_UTILS_DIR}/make_ports.py $(BUILD_DIR)/gtxe2_common_pins.csv $(BUILD_DIR)/gtxe2_common_ports.json --special-pins $(SPECIAL_PINS)
database: ${BUILD_DIR}/segbits_gtx_common.db $(BUILD_DIR)/gtxe2_common_ports.json
${BUILD_DIR}/segbits_gtx_common.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -o ${BUILD_DIR}/segbits_gtx_common.rdb $$(find $(SPECIMENS) -name "segdata_gtx_common*")
${BUILD_DIR}/segbits_gtx_common.db: ${BUILD_DIR}/segbits_gtx_common.rdb
${XRAY_DBFIXUP} --db-root ${BUILD_DIR} --zero-db bits.dbf \
--seg-fn-in ${BUILD_DIR}/segbits_gtx_common.rdb \
--seg-fn-out ${BUILD_DIR}/segbits_gtx_common.db
${XRAY_MASKMERGE} ${BUILD_DIR}/mask_gtx_common.db $$(find $(SPECIMENS) -name "segdata_gtx_common*")
pushdb:
mkdir -p $(CELLS_DATA_DIR)
cp attrs.json $(CELLS_DATA_DIR)/gtxe2_common_attrs.json
cp $(BUILD_DIR)/gtxe2_common_ports.json $(CELLS_DATA_DIR)/gtxe2_common_ports.json
BUILD_DIR=$(BUILD_DIR) source pushdb.sh
.PHONY: database pushdb

View File

@ -0,0 +1,33 @@
GTXE2\_COMMON Primitive Configuration fuzzer
============================================
This fuzzer is used to document the parameters corresponding to the GTXE2\_COMMON primitive.
It uses pre-built JSON containing a dictionary of parameters, each one with four attributes:
- Type: one of Binary, Integer, String, Boolean.
- Values: all possible values that this parameter can assume. In case of `BIN` types, the values list contains only the maximum value reachable.
- Digits: number of digits (or bits) required to use a parameter.
- Encoding: This is present only for `INT` types of parameters. These reflect the actual encoding of the parameter value in the bit array.
E.g.:
```json
{
"PLL0_REFCLK_DIV": {
"type": "INT",
"values": [1, 2],
"encoding": [16, 0],
"digits": 5
}
}
```
In addition, there exist wires and PIPs that allow the connections of the `GTREFCLK` ports to clocks coming from the device fabric instead of the `IBUFDS_GTE2` primitive.
In fact, if the clock comes from the device fabric, the physical `GTGREFCLK[01]` port is used instead of the `GTREFCLK[01]` one (even though the design's primitive port is always `GTREFCLK`).
In the [User Guide (pg 27)](https://www.xilinx.com/support/documentation/user_guides/ug482_7Series_GTX_Transceivers.pdf), it is stated that the `GTGREFCLK[01]` port is used for "internal testing purposes".
Using this port is highly discouraged to get the reference clock from the fabric, as the recommended way is to get the clock from an external source using the `IBUFDS_GTE2` primitive.
Therefore, in addition to the parameters, `IN_USE` and `ZINV\INV` features, this fuzzer documents also the `GTREFCLK[01]_USED` and `BOTH_GTREFCLK[01]_USED` features.

View File

@ -0,0 +1,83 @@
{
"QPLL_CFG": {
"type": "BIN",
"values": [134150145],
"digits": 27
},
"QPLL_CP": {
"type": "BIN",
"values": [1023],
"digits": 10
},
"QPLL_CP_MONITOR_EN": {
"type": "BIN",
"values": [1],
"digits": 1
},
"QPLL_DMONITOR_SEL": {
"type": "BIN",
"values": [1],
"digits": 1
},
"QPLL_REFCLK_DIV": {
"type": "INT",
"values": [1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20],
"encoding": [16, 0, 1, 2, 3, 5, 6, 7, 13, 14, 15],
"digits": 5
},
"QPLL_FBDIV": {
"type": "BIN",
"values": [496],
"digits": 10
},
"QPLL_FBDIV_MONITOR_EN": {
"type": "BIN",
"values": [1],
"digits": 1
},
"QPLL_FBDIV_RATIO": {
"type": "BIN",
"values": [1],
"digits": 1
},
"QPLL_LOCK_CFG": {
"type": "BIN",
"values": [65535],
"digits": 16
},
"QPLL_INIT_CFG": {
"type": "BIN",
"values": [16777215],
"digits": 24
},
"QPLL_LPF": {
"type": "BIN",
"values": [15],
"digits": 4
},
"COMMON_CFG": {
"type": "BIN",
"values": [4294836225],
"digits": 32
},
"QPLL_CLKOUT_CFG": {
"type": "BIN",
"values": [15],
"digits": 4
},
"QPLL_COARSE_FREQ_OVRD": {
"type": "BIN",
"values": [63],
"digits": 5
},
"QPLL_COARSE_FREQ_OVRD_EN": {
"type": "BIN",
"values": [1],
"digits": 1
},
"BIAS_CFG": {
"type": "BIN",
"values": [18445618199572250625],
"digits": 64
}
}

View File

View File

@ -0,0 +1,149 @@
#!/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
import os
from enum import Enum
from prjxray.segmaker import Segmaker
#from icecream import ic
INT = "INT"
BIN = "BIN"
def bitfilter_gtx_common_mid(frame, bit):
# Filter out non interesting bits.
word = int(bit / 32)
if word < 44 or word > 56:
return False
return True
def bitfilter_gtx_common(frame, bit):
# Filter out non interesting bits.
word = int(bit / 32)
if word < 44 or word > 56:
return False
return True
def main():
segmk = Segmaker("design.bits")
fuz_dir = os.getenv("FUZDIR", None)
assert fuz_dir
with open(os.path.join(fuz_dir, "attrs.json"), "r") as attr_file:
attrs = json.load(attr_file)
print("Loading tags")
with open("params.json") as f:
params_dict = json.load(f)
tile_type = params_dict["tile_type"]
params_list = params_dict["params"]
sites_in_tile = dict()
for params in params_list:
site = params["site"]
tile = params["tile"]
if "GTXE2_COMMON" not in site:
continue
sites_in_tile[tile] = site
in_use = params["IN_USE"]
segmk.add_site_tag(site, "IN_USE", in_use)
if in_use:
for param, param_info in attrs.items():
value = params[param]
param_type = param_info["type"]
param_digits = param_info["digits"]
param_values = param_info["values"]
if param_type == INT:
param_encodings = param_info["encoding"]
param_encoding = param_encodings[param_values.index(value)]
bitstr = [
int(x) for x in "{value:0{digits}b}".format(
value=param_encoding, digits=param_digits)[::-1]
]
for i in range(param_digits):
segmk.add_site_tag(
site, '%s[%u]' % (param, i), bitstr[i])
else:
assert param_type == BIN
bitstr = [
int(x) for x in "{value:0{digits}b}".format(
value=value, digits=param_digits)[::-1]
]
for i in range(param_digits):
segmk.add_site_tag(
site, "%s[%u]" % (param, i), bitstr[i])
for param in ["QPLLLOCKDETCLK", "DRPCLK"]:
segmk.add_site_tag(site, "INV_" + param, params[param])
for param in ["GTREFCLK0_USED", "GTREFCLK1_USED",
"BOTH_GTREFCLK_USED"]:
segmk.add_site_tag(site, param, params[param])
segmk.add_site_tag(site, "ENABLE_DRP", params["ENABLE_DRP"])
for params in params_list:
site = params["site"]
if "IBUFDS_GTE2" not in site:
continue
in_use = params["IN_USE"]
segmk.add_site_tag(site, "IN_USE", in_use)
if in_use:
tile = params["tile"]
for param in ["CLKRCV_TRST", "CLKCM_CFG"]:
value = params[param]
segmk.add_site_tag(site, param, "TRUE" in value)
bitstr = [
int(x) for x in "{value:0{digits}b}".format(
value=params["CLKSWING_CFG"], digits=2)[::-1]
]
gtx_common_site = sites_in_tile[tile]
for i in range(2):
segmk.add_site_tag(
gtx_common_site, "IBUFDS_GTE2.CLKSWING_CFG[%u]" % (i),
bitstr[i])
if tile_type.startswith("GTX_COMMON_MID"):
bitfilter = bitfilter_gtx_common_mid
elif tile_type == "GTX_COMMON":
bitfilter = bitfilter_gtx_common
else:
assert False, tile_type
segmk.compile(bitfilter=bitfilter)
segmk.write()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,31 @@
# 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
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property IS_ENABLED 0 [get_drc_checks {NSTD-1}]
set_property IS_ENABLED 0 [get_drc_checks {UCIO-1}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-48}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-47}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-51}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-1619}]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,15 @@
# 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
source "$::env(XRAY_DIR)/utils/utils.tcl"
create_project -force -name design -part $::env(XRAY_PART)
set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
dump_pins $::env(FILE_NAME) GTXE2_COMMON

View File

@ -0,0 +1,22 @@
#!/bin/bash
# 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
if ! test $(find ${BUILD_DIR} -name "segdata_gtx_common_mid_right.txt" | wc -c) -eq 0
then
${XRAY_MERGEDB} gtx_common_mid_right ${BUILD_DIR}/segbits_gtx_common.db
${XRAY_MERGEDB} mask_gtx_common_mid_right ${BUILD_DIR}/mask_gtx_common.db
${XRAY_MERGEDB} gtx_common_mid_left ${BUILD_DIR}/segbits_gtx_common.db
${XRAY_MERGEDB} mask_gtx_common_mid_left ${BUILD_DIR}/mask_gtx_common.db
fi
if ! test $(find ${BUILD_DIR} -name "segdata_gtx_common.txt" | wc -c) -eq 0
then
${XRAY_MERGEDB} gtx_common ${BUILD_DIR}/segbits_gtx_common.db
${XRAY_MERGEDB} mask_gtx_common ${BUILD_DIR}/mask_gtx_common.db
fi

View File

@ -0,0 +1,258 @@
#!/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
import os
import random
from collections import namedtuple
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray import verilog
from prjxray.lut_maker import LutMaker
from prjxray.db import Database
INT = "INT"
BIN = "BIN"
def gen_sites(tile, site, filter_cmt=None):
db = Database(util.get_db_root(), util.get_part())
grid = db.grid()
for tile_name in sorted(grid.tiles()):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
if tile not in gridinfo.tile_type:
continue
else:
tile_type = gridinfo.tile_type
for site_name, site_type in gridinfo.sites.items():
if site_type != site:
continue
cmt = gridinfo.clock_region
if filter_cmt is not None and cmt != filter_cmt:
continue
yield tile_name, tile_type, site_name, cmt
def main():
print(
'''
module top(
input wire in,
output wire out
);
assign out = in;
''')
luts = LutMaker()
params_dict = {"tile_type": None}
params_list = list()
clkswing_cfg_tiles = dict()
ibufds_out_wires = dict()
for tile_name, _, site_name, _ in gen_sites("GTX_COMMON", "IBUFDS_GTE2"):
# Both the IBUFDS_GTE2 in the same tile need to have
# the same CLKSWING_CFG parameter
if tile_name not in clkswing_cfg_tiles:
clkswing_cfg = random.randint(0, 3)
clkswing_cfg_tiles[tile_name] = clkswing_cfg
else:
clkswing_cfg = clkswing_cfg_tiles[tile_name]
in_use = bool(random.randint(0, 9))
params = {
"site":
site_name,
"tile":
tile_name,
"IN_USE":
in_use,
"CLKRCV_TRST":
verilog.quote("TRUE" if random.randint(0, 1) else "FALSE"),
"CLKCM_CFG":
verilog.quote("TRUE" if random.randint(0, 1) else "FALSE"),
"CLKSWING_CFG":
clkswing_cfg,
}
if in_use:
ibufds_out_wire = "{}_O".format(site_name)
if tile_name not in ibufds_out_wires:
ibufds_out_wires[tile_name] = list()
ibufds_out_wires[tile_name].append(
(ibufds_out_wire, int(site_name[-1]) % 2))
print("wire {};".format(ibufds_out_wire))
print("(* KEEP, DONT_TOUCH, LOC=\"{}\" *)".format(site_name))
print(
"""
IBUFDS_GTE2 #(
.CLKRCV_TRST({CLKRCV_TRST}),
.CLKCM_CFG({CLKCM_CFG}),
.CLKSWING_CFG({CLKSWING_CFG})
) {site} (
.O({out})
);""".format(**params, out=ibufds_out_wire))
params_list.append(params)
DRP_PORTS = [
("DRPCLK", "clk"), ("DRPEN", "in"), ("DRPWE", "in"), ("DRPRDY", "out")
]
for tile_name, tile_type, site_name, cmt in gen_sites("GTX_COMMON",
"GTXE2_COMMON"):
params_dict["tile_type"] = tile_type
params = dict()
params['site'] = site_name
params['tile'] = tile_name
verilog_attr = ""
verilog_attr = "#("
fuz_dir = os.getenv("FUZDIR", None)
assert fuz_dir
with open(os.path.join(fuz_dir, "attrs.json"), "r") as attrs_file:
attrs = json.load(attrs_file)
in_use = bool(random.randint(0, 9))
params["IN_USE"] = in_use
if in_use:
for param, param_info in attrs.items():
param_type = param_info["type"]
param_values = param_info["values"]
param_digits = param_info["digits"]
if param_type == INT:
value = random.choice(param_values)
value_str = value
else:
assert param_type == BIN
value = random.randint(0, param_values[0])
value_str = "{digits}'b{value:0{digits}b}".format(
value=value, digits=param_digits)
params[param] = value
verilog_attr += """
.{}({}),""".format(param, value_str)
verilog_ports = ""
for param in ["QPLLLOCKDETCLK", "DRPCLK"]:
is_inverted = random.randint(0, 1)
params[param] = is_inverted
verilog_attr += """
.IS_{}_INVERTED({}),""".format(param, is_inverted)
verilog_ports += """
.{}({}),""".format(param, luts.get_next_output_net())
verilog_attr = verilog_attr.rstrip(",")
verilog_attr += "\n)"
for param in ["GTREFCLK0_USED", "GTREFCLK1_USED",
"BOTH_GTREFCLK_USED"]:
params[param] = 0
if tile_name in ibufds_out_wires:
gtrefclk_ports_used = 0
for wire, location in ibufds_out_wires[tile_name]:
if random.random() < 0.5:
continue
verilog_ports += """
.GTREFCLK{}({}),""".format(location, wire)
gtrefclk_ports_used += 1
params["GTREFCLK{}_USED".format(location)] = 1
if gtrefclk_ports_used == 2:
params["BOTH_GTREFCLK_USED"] = 1
enable_drp = random.randint(0, 1)
params["ENABLE_DRP"] = enable_drp
for _, _, channel_site_name, _ in gen_sites("GTX_CHANNEL",
"GTXE2_CHANNEL", cmt):
if not enable_drp:
break
verilog_ports_channel = ""
for port, direction in DRP_PORTS:
if direction == "in":
verilog_ports_channel += """
.{}({}),""".format(port, luts.get_next_output_net())
elif direction == "clk":
# DRPCLK needs to come from a clock source
print(
"""
wire clk_bufg_{site};
(* KEEP, DONT_TOUCH *)
BUFG bufg_{site} (.O(clk_bufg_{site}));""".format(site=channel_site_name))
verilog_ports_channel += """
.{}(clk_bufg_{}),""".format(port, channel_site_name)
elif direction == "out":
verilog_ports_channel += """
.{}({}),""".format(port, luts.get_next_input_net())
print(
"""
(* KEEP, DONT_TOUCH, LOC=\"{site}\" *)
GTXE2_CHANNEL {site} (
{ports}
);""".format(ports=verilog_ports_channel.rstrip(","), site=channel_site_name))
print(
"""
(* KEEP, DONT_TOUCH, LOC=\"{site}\" *)
GTXE2_COMMON {attrs} {site} (
{ports}
);""".format(
attrs=verilog_attr,
ports=verilog_ports.rstrip(","),
site=site_name))
params_list.append(params)
for l in luts.create_wires_and_luts():
print(l)
print("endmodule")
params_dict["params"] = params_list
with open('params.json', 'w') as f:
json.dump(params_dict, f, indent=2)
if __name__ == '__main__':
main()

View File

@ -191,6 +191,9 @@ $(eval $(call fuzzer,065-gtp-common-pips,005-tilegrid,part))
$(eval $(call fuzzer,065b-gtp-common-pips,005-tilegrid,part))
$(eval $(call fuzzer,066-gtp-int-pips,005-tilegrid,all))
endif
ifeq ($(XRAY_DATABASE),kintex7)
$(eval $(call fuzzer,063-gtx-common-conf,005-tilegrid,part))
endif
endif
endif
$(eval $(call fuzzer,100-dsp-mskpat,005-tilegrid,all))