diff --git a/docs/dev_database/common/cell_data.rst b/docs/dev_database/common/cell_data.rst new file mode 100644 index 00000000..07dbf8da --- /dev/null +++ b/docs/dev_database/common/cell_data.rst @@ -0,0 +1,82 @@ +=============== +cell data files +=============== + +The *cell data* files are meant for specific primitives which have a common attribute format. The data contained in these files is generated/copied from the corresponding primitives' fuzzers. + +Naming convention +----------------- + +The naming scheme for the cell data files is the following:: + + _.json + +Example files: + + - ``gtpe2_common_attrs.json`` + - ``gtpe2_channel_ports.json`` + +File format +----------- + +There are two main data file types: + + - *Ports* + - *Attributes* + +Attributes files +~~~~~~~~~~~~~~~~ + +This is a JSON file containing a dictionary of parameters, each one with, at most, four attributes: + + - Type: one of BIN, INT, STR, BOOL. + - 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 enable 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. + +As an example of parameter please, refer to the following:: + + { + "PLL0_REFCLK_DIV": { + "type": "INT", + "values": [1, 2], + "encoding": [16, 0], + "digits": 5 + }, + "RXLPMRESET_TIME": { + "type": "BIN", + "values": [127], + "digits": 7 + }, + "RX_XCLK_SEL": { + "type": "STR", + "values": ["RXREC", "RXUSR"], + "digits": 1 + }, + "TX_LOOPBACK_DRIVE_HIZ": { + "type": "BOOL", + "values": ["FALSE", "TRUE"], + "digits": 1 + }, + } + +Ports files +~~~~~~~~~~~ + +This is a JSON file containing a dictionary of ports, each one with two attributes: + + - Direction: Corresponds to the port directiona and can have the ``input`` or ``output`` values. + - Width: Indicates the width of the port bus. + +As an example of parameter please, refer to the following:: + + { + "CFGRESET": { + "direction": "input", + "width": 1 + }, + "CLKRSVD0": { + "direction": "input", + "width": 1 + } + } diff --git a/docs/dev_database/common/index.rst b/docs/dev_database/common/index.rst index 939999e8..0817f9da 100644 --- a/docs/dev_database/common/index.rst +++ b/docs/dev_database/common/index.rst @@ -13,3 +13,4 @@ that are common for all Xilinx series 7 chip architectures. tile_type ppips mask + cell_data diff --git a/fuzzers/063-gtp-common-conf/Makefile b/fuzzers/063-gtp-common-conf/Makefile index 4e939577..f865c856 100644 --- a/fuzzers/063-gtp-common-conf/Makefile +++ b/fuzzers/063-gtp-common-conf/Makefile @@ -16,6 +16,7 @@ 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 @@ -36,7 +37,17 @@ clean: .PHONY: all run clean -database: ${BUILD_DIR}/segbits_gtp_common.db +# 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)/gtpe2_common_ports.csv: generate_ports.tcl + env FILE_NAME=$(BUILD_DIR)/gtpe2_common_pins.csv ${XRAY_VIVADO} -mode batch -source generate_ports.tcl + +$(BUILD_DIR)/gtpe2_common_ports.json: $(BUILD_DIR)/gtpe2_common_ports.csv + python3 ${XRAY_UTILS_DIR}/make_ports.py $(BUILD_DIR)/gtpe2_common_pins.csv $(BUILD_DIR)/gtpe2_common_ports.json --special-pins $(SPECIAL_PINS) + +database: ${BUILD_DIR}/segbits_gtp_common.db $(BUILD_DIR)/gtpe2_common_ports.json ${BUILD_DIR}/segbits_gtp_common.rdb: $(SPECIMENS_OK) ${XRAY_SEGMATCH} -o ${BUILD_DIR}/segbits_gtp_common.rdb $$(find $(SPECIMENS) -name "segdata_gtp_common*") @@ -48,6 +59,9 @@ ${BUILD_DIR}/segbits_gtp_common.db: ${BUILD_DIR}/segbits_gtp_common.rdb ${XRAY_MASKMERGE} ${BUILD_DIR}/mask_gtp_common.db $$(find $(SPECIMENS) -name "segdata_gtp_common*") pushdb: + mkdir -p $(CELLS_DATA_DIR) + cp attrs.json $(CELLS_DATA_DIR)/gtpe2_common_attrs.json + cp $(BUILD_DIR)/gtpe2_common_ports.json $(CELLS_DATA_DIR)/gtpe2_common_ports.json BUILD_DIR=$(BUILD_DIR) source pushdb.sh .PHONY: database pushdb diff --git a/fuzzers/063-gtp-common-conf/generate.py b/fuzzers/063-gtp-common-conf/generate.py index 073d696b..06cc0075 100644 --- a/fuzzers/063-gtp-common-conf/generate.py +++ b/fuzzers/063-gtp-common-conf/generate.py @@ -62,6 +62,8 @@ def main(): 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"] @@ -69,6 +71,8 @@ def main(): if "GTPE2_COMMON" not in site: continue + sites_in_tile[tile] = site + in_use = params["IN_USE"] segmk.add_site_tag(site, "IN_USE", in_use) @@ -109,7 +113,7 @@ def main(): "BOTH_GTREFCLK_USED"]: segmk.add_site_tag(site, param, params[param]) - segmk.add_tile_tag(tile, "ENABLE_DRP", params["ENABLE_DRP"]) + segmk.add_site_tag(site, "ENABLE_DRP", params["ENABLE_DRP"]) for params in params_list: site = params["site"] @@ -132,9 +136,11 @@ def main(): value=params["CLKSWING_CFG"], digits=2)[::-1] ] + gtp_common_site = sites_in_tile[tile] for i in range(2): - segmk.add_tile_tag( - tile, "IBUFDS_GTE2.CLKSWING_CFG[%u]" % (i), bitstr[i]) + segmk.add_site_tag( + gtp_common_site, "IBUFDS_GTE2.CLKSWING_CFG[%u]" % (i), + bitstr[i]) if tile_type.startswith("GTP_COMMON_MID"): bitfilter = bitfilter_gtp_common_mid diff --git a/fuzzers/063-gtp-common-conf/generate_ports.tcl b/fuzzers/063-gtp-common-conf/generate_ports.tcl new file mode 100644 index 00000000..75f7c7ff --- /dev/null +++ b/fuzzers/063-gtp-common-conf/generate_ports.tcl @@ -0,0 +1,36 @@ +# 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 dump_pins {file_name site_prefix} { + set fp [open $file_name w] + + puts $fp "name,is_input,is_output" + set site [lindex [get_sites $site_prefix*] 0] + + set pins [get_site_pins -of_objects $site] + foreach pin $pins { + set connected_pip [get_pips -of_objects [get_nodes -of_objects $pin]] + + if { $connected_pip == "" } { + continue + } + + set pin_name [lindex [split $pin "/"] 1] + set is_input [get_property IS_INPUT $pin] + set is_output [get_property IS_OUTPUT $pin] + + puts $fp "$pin_name,$is_input,$is_output" + } + close $fp +} + +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) GTPE2_COMMON diff --git a/fuzzers/064-gtp-channel-conf/Makefile b/fuzzers/064-gtp-channel-conf/Makefile index ebf729c9..ecc6eb9e 100644 --- a/fuzzers/064-gtp-channel-conf/Makefile +++ b/fuzzers/064-gtp-channel-conf/Makefile @@ -16,6 +16,7 @@ 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 @@ -34,7 +35,17 @@ clean: .PHONY: all run clean -database: ${BUILD_DIR}/segbits_gtp_channelx.db +# 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 = CLKRSVD0,CLKRSVD1,GTREFCLK0,GTREFCLK1,GTNORTHREFCLK0,GTNORTHREFCLK1,GTSOUTHREFCLK0,GTSOUTHREFCLK1,RXUSRCLK,RXUSRCLK2,TXUSRCLK,TXUSRCLK2,RXOSINTID0,PMARSVDIN0,PMARSVDIN1,PMARSVDIN2,PMARSVDIN3,PMARSVDIN4,PMARSVDOUT0,PMARSVDOUT1 + +$(BUILD_DIR)/gtpe2_channel_ports.csv: + env FILE_NAME=$(BUILD_DIR)/gtpe2_channel_pins.csv ${XRAY_VIVADO} -mode batch -source generate_ports.tcl + +$(BUILD_DIR)/gtpe2_channel_ports.json: $(BUILD_DIR)/gtpe2_channel_ports.csv + python3 ${XRAY_UTILS_DIR}/make_ports.py $(BUILD_DIR)/gtpe2_channel_pins.csv $(BUILD_DIR)/gtpe2_channel_ports.json --special-pins $(SPECIAL_PINS) + +database: ${BUILD_DIR}/segbits_gtp_channelx.db $(BUILD_DIR)/gtpe2_channel_ports.json ${BUILD_DIR}/segbits_gtp_channelx.rdb: $(SPECIMENS_OK) ${XRAY_SEGMATCH} -c 9 -o ${BUILD_DIR}/segbits_gtp_channelx.rdb $$(find $(SPECIMENS) -name "segdata_gtp_channel_[0123]*") @@ -46,6 +57,9 @@ ${BUILD_DIR}/segbits_gtp_channelx.db: ${BUILD_DIR}/segbits_gtp_channelx.rdb ${XRAY_MASKMERGE} ${BUILD_DIR}/mask_gtp_channelx.db $$(find $(SPECIMENS) -name "segdata_gtp_channel_[0123]*") pushdb: + mkdir -p $(CELLS_DATA_DIR) + cp attrs.json $(CELLS_DATA_DIR)/gtpe2_channel_attrs.json + cp $(BUILD_DIR)/gtpe2_channel_ports.json $(CELLS_DATA_DIR)/gtpe2_channel_ports.json BUILD_DIR=$(BUILD_DIR) source pushdb.sh .PHONY: database pushdb diff --git a/fuzzers/064-gtp-channel-conf/generate_ports.tcl b/fuzzers/064-gtp-channel-conf/generate_ports.tcl new file mode 100644 index 00000000..f8479240 --- /dev/null +++ b/fuzzers/064-gtp-channel-conf/generate_ports.tcl @@ -0,0 +1,36 @@ +# 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 dump_pins {file_name site_prefix} { + set fp [open $file_name w] + + puts $fp "name,is_input,is_output" + set site [lindex [get_sites $site_prefix*] 0] + + set pins [get_site_pins -of_objects $site] + foreach pin $pins { + set connected_pip [get_pips -of_objects [get_nodes -of_objects $pin]] + + if { $connected_pip == "" } { + continue + } + + set pin_name [lindex [split $pin "/"] 1] + set is_input [get_property IS_INPUT $pin] + set is_output [get_property IS_OUTPUT $pin] + + puts $fp "$pin_name,$is_input,$is_output" + } + close $fp +} + +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) GTPE2_CHANNEL diff --git a/utils/make_ports.py b/utils/make_ports.py new file mode 100644 index 00000000..e31600c3 --- /dev/null +++ b/utils/make_ports.py @@ -0,0 +1,108 @@ +#!/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 +""" +This script loads the pin dump of the desired BEL from Vivado and groups pins into ports. + +Ports that are not connected to the PL are not included. These ports are usually test and +debug related ports, which are not useful from a P&R perspective. + +Ports are then written to a JSON file. +""" +import argparse +import csv +import json +import re + +from collections import defaultdict + + +def main(): + + BUS_REGEX = re.compile("(.*[A-Z_])([0-9]+)$") + + # Parse arguments + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + parser.add_argument("csv", type=str, help="BEL pin dump file") + parser.add_argument( + "json", + type=str, + help="Output JSON file with BEL pins grouped into ports") + + parser.add_argument( + "--special-pins", + default="", + type=str, + required=False, + help="Some pins cannot be decoded with the regex") + + args = parser.parse_args() + + # Load pin dump + with open(args.csv, "r") as fp: + pin_dump = list(csv.DictReader(fp)) + + # Group pins into ports + ports = defaultdict(lambda: {"direction": None, "width": 0}) + + special_pins = args.special_pins.split(",") + + for pin in list(pin_dump): + pin_name = pin["name"] + + name = None + if pin_name in special_pins: + # Full match + name = pin_name + else: + # Partial match + for special_pin in special_pins: + if pin_name.startswith(special_pin): + name = special_pin + break + + if name is None: + match = BUS_REGEX.match(pin_name) + if match: + name = match.group(1) + else: + name = pin_name + + # Get direction + is_input = int(pin["is_input"]) + is_output = int(pin["is_output"]) + + if is_input: + direction = "input" + elif is_output: + direction = "output" + else: + assert False, pin + + # Add to port + port = ports[name] + + if port["direction"] is None: + port["direction"] = direction + else: + assert port["direction"] == direction, (port, direction, name) + + port["width"] += 1 + + # Write pin ports to a JSON file + with open(args.json, "w") as fp: + json.dump(ports, fp, indent=1, sort_keys=True) + + +if __name__ == "__main__": + main()