mpm/fpga: x4xx: Major updates in preparation for future devices
FPGA: - Split up MB registers that control daughterboard specific settings so that daughterboards 0 and 1 could have different setings, in preparation for future devices that require different settings. This requires a compat number bump to 8.0. - Add registers for additional RFDC information, including the block/tile mapping of the individual channels, and information about resampling capabilities - Identify sections of code that would be specific to X410/ZBX and move them to their own headers, so it's trivial to add device-specific sections of code instead for other devices in the future. - This includes constraints for clocks and I/O pins. - Remove ability to do timed ctrlport transactions to the MB CPLD, this was unused and possibly broken. - Move daughterboard-specific code into its own code location (dboards/zbx) - Move X410-specific register documentation to its own location (doc/X410) - Refactor Makefiles to split out X410/ZBX specific components and allow switching between device types - Add 512-bit AXI interconnects - Make number of timekeepers configurable (X410 keeps the single timekeeper) MPM: - Required compat is bumped to 8.0 - Now supports new registers for detecting DSP capabilities and multi-rate settings for the daughterboards - Adds MMCM controls (currently unused) Co-authored-by: Wade Fife <wade.fife@ni.com> Co-authored-by: Ryan Marlow <ryan@lmarlow.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Original-commit: c1d268917ea65dd9c5a42366014cb96d3c025223
This commit is contained in:
committed by
Martin Braun
co-authored by
Wade Fife
Ryan Marlow
Martin Braun
Humberto Jimenez
parent
ffdcc016cc
commit
adf6f576c6
@@ -0,0 +1,165 @@
|
||||
#
|
||||
# Copyright 2022 Ettus Research, a National Instruments Company
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
|
||||
""" Vivado IP sub-core re-targeting.
|
||||
|
||||
Script to update the sub-cores in a directory to a specific
|
||||
part number
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Parse command line options
|
||||
def get_options():
|
||||
"""Parse script arguments."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Utility script to modify subcores for a Xilinx IP XCI file"
|
||||
)
|
||||
parser.add_argument(
|
||||
"xci_filepath", type=str, default=None, help="Name for the IP core"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--target",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Input value for target. Must be of the form <arch>/<device>/<package>/<speedgrade>/<silicon revision>",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--name", type=str, default=None, help="Input value for new IP name"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output_dir", type=str, default=".", help="Build directory for IP"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if not args.xci_filepath:
|
||||
print("ERROR: Please specify the location for the XCI file to operate on\n")
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
if not os.path.isfile(args.xci_filepath):
|
||||
print(
|
||||
"ERROR: XCI File "
|
||||
+ args.xci_filepath
|
||||
+ " could not be accessed or is not a file.\n"
|
||||
)
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
return args
|
||||
|
||||
|
||||
def get_match_str(item):
|
||||
"""Produce the string to an XML parameter with a value."""
|
||||
return (
|
||||
'(.*\<spirit:configurableElementValue spirit:referenceId=".*\.'
|
||||
+ item
|
||||
+ '"\>)(.+)(\</spirit:configurableElementValue\>)'
|
||||
)
|
||||
|
||||
|
||||
def get_empty_match_str(item):
|
||||
"""Produce the string to an XML parameter without a value."""
|
||||
return (
|
||||
'(.*\<spirit:configurableElementValue spirit:referenceId=".*\.' + item + '")/\>'
|
||||
)
|
||||
|
||||
|
||||
def retarget_subcore(path, file, output_dir, target_tok):
|
||||
"""Update target parameter for the specified sub-core."""
|
||||
# Read XCI File
|
||||
with open(os.path.join(path, file)) as in_file:
|
||||
xci_lines = in_file.readlines()
|
||||
|
||||
replace_dict = {
|
||||
"ARCHITECTURE": target_tok[0],
|
||||
"DEVICE": target_tok[1],
|
||||
"PACKAGE": target_tok[2],
|
||||
"SPEEDGRADE": target_tok[3],
|
||||
"C_XDEVICEFAMILY": target_tok[0],
|
||||
"C_FAMILY": target_tok[0],
|
||||
"C_XDEVICE": target_tok[1],
|
||||
}
|
||||
if len(target_tok) > 4:
|
||||
replace_dict["TEMPERATURE_GRADE"] = target_tok[4]
|
||||
if len(target_tok) > 5:
|
||||
replace_dict["SILICON_REVISION"] = target_tok[5]
|
||||
out_xci_filename = os.path.join(os.path.abspath(output_dir), os.path.basename(file))
|
||||
|
||||
# Write files with modified parameters
|
||||
with open(out_xci_filename, "w") as out_file:
|
||||
for r_line in xci_lines:
|
||||
w_line = r_line
|
||||
m = re.search(
|
||||
get_match_str("(" + "|".join(list(replace_dict.keys())) + ")"), r_line
|
||||
)
|
||||
if m is not None:
|
||||
w_line = m.group(1) + replace_dict[m.group(2)] + m.group(4) + "\n"
|
||||
else:
|
||||
m = re.search(
|
||||
get_empty_match_str(
|
||||
"(" + "|".join(list(replace_dict.keys())) + ")"
|
||||
),
|
||||
r_line,
|
||||
)
|
||||
if m is not None:
|
||||
w_line = (
|
||||
m.group(1)
|
||||
+ ">"
|
||||
+ replace_dict[m.group(2)]
|
||||
+ "</spirit:configurableElementValue>\n"
|
||||
)
|
||||
out_file.write(w_line)
|
||||
|
||||
|
||||
def main():
|
||||
"""Perform directory traversal to detect and update sub-cores."""
|
||||
args = get_options()
|
||||
|
||||
# Validate arguments
|
||||
if not os.path.isdir(args.output_dir):
|
||||
print(
|
||||
"ERROR: IP Build directory "
|
||||
+ args.output_dir
|
||||
+ " could not be accessed or is not a directory."
|
||||
)
|
||||
sys.exit(1)
|
||||
if not args.target:
|
||||
print("ERROR: No target specified.")
|
||||
sys.exit(1)
|
||||
target_tok = args.target.split("/")
|
||||
if len(target_tok) < 4:
|
||||
print(
|
||||
"ERROR: Invalid target format. Must be <arch>/<device>/<package>/<speedgrade>/<tempgrade>/<silicon revision>"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
sub_cores = []
|
||||
|
||||
# Detect sub-cores
|
||||
ip_dir, ip_name = os.path.split(args.xci_filepath)
|
||||
for path, _, files in os.walk(ip_dir):
|
||||
for name in files:
|
||||
if name.endswith("xci"):
|
||||
sub_cores.append(os.path.join(path, name))
|
||||
|
||||
# Get the relative path for each IP core detected
|
||||
relative_paths = [os.path.relpath(path, ip_dir) for path in sub_cores]
|
||||
|
||||
# Remove main core
|
||||
relative_paths.remove(ip_name)
|
||||
|
||||
for rp in relative_paths:
|
||||
retarget_subcore(
|
||||
os.path.join(ip_dir, os.path.split(rp)[0]),
|
||||
os.path.split(rp)[1],
|
||||
os.path.join(args.output_dir, os.path.split(rp)[0]),
|
||||
target_tok,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user