diff options
author | Martin Braun <martin.braun@ettus.com> | 2020-05-14 15:48:40 -0700 |
---|---|---|
committer | Wade Fife <wade.fife@ettus.com> | 2020-05-18 17:57:38 -0500 |
commit | 676c3a37867f0e19476e9dc8495127bb3208a1a0 (patch) | |
tree | 4312bbc3baf53c39367d886e873bff41139b5a5c /fpga/usrp3/tools/scripts | |
parent | bba0cddfadcb744e8a6fae27d57ba8d3995eaf64 (diff) | |
download | uhd-676c3a37867f0e19476e9dc8495127bb3208a1a0.tar.gz uhd-676c3a37867f0e19476e9dc8495127bb3208a1a0.tar.bz2 uhd-676c3a37867f0e19476e9dc8495127bb3208a1a0.zip |
fpga: tools: Remove uhd_image_builder
The image builder was replaced by rfnoc_image_builder, and has been
obsolete since then.
Diffstat (limited to 'fpga/usrp3/tools/scripts')
-rw-r--r-- | fpga/usrp3/tools/scripts/auto_inst_e310.yml | 22 | ||||
-rw-r--r-- | fpga/usrp3/tools/scripts/auto_inst_x310.yml | 29 | ||||
-rwxr-xr-x | fpga/usrp3/tools/scripts/uhd_image_builder.py | 537 | ||||
-rwxr-xr-x | fpga/usrp3/tools/scripts/uhd_image_builder_gui.py | 656 |
4 files changed, 0 insertions, 1244 deletions
diff --git a/fpga/usrp3/tools/scripts/auto_inst_e310.yml b/fpga/usrp3/tools/scripts/auto_inst_e310.yml deleted file mode 100644 index 5842e17c2..000000000 --- a/fpga/usrp3/tools/scripts/auto_inst_e310.yml +++ /dev/null @@ -1,22 +0,0 @@ -# auto-inst file for E310 -# To regenerate rfnoc_ce_auto_inst_e310.v: -# ./uhd_image_builder.py -d e310 -t E310_RFNOC_sg3 -y auto_inst_e310.yml -o rfnoc_ce_auto_inst_e310.v - -- block: axi_fifo_loopback - parameters: - -- block: window - parameters: - -- block: fft - parameters: - -- block: fosphor - parameters: - MTU: 12 - -- block: axi_fifo_loopback - parameters: - -- block: fir_filter - parameters: diff --git a/fpga/usrp3/tools/scripts/auto_inst_x310.yml b/fpga/usrp3/tools/scripts/auto_inst_x310.yml deleted file mode 100644 index 26548031b..000000000 --- a/fpga/usrp3/tools/scripts/auto_inst_x310.yml +++ /dev/null @@ -1,29 +0,0 @@ -# auto-inst file for X310 -# To regenerate rfnoc_ce_auto_inst_x310.v: -# ./uhd_image_builder.py -d x310 -t X310_RFNOC_HG -m 10 --fill-with-fifos -y auto_inst_x310.yml -o rfnoc_ce_auto_inst_x310.v - -- block: ddc - parameters: - NOC_ID: 64'hDDC0_0000_0000_0001 - NUM_CHAINS: 1 - -- block: duc - parameters: - -- block: fft - parameters: - -- block: window - parameters: - -- block: fir_filter - parameters: - -- block: siggen - parameters: - -- block: keep_one_in_n - parameters: - -- block: fosphor - parameters: diff --git a/fpga/usrp3/tools/scripts/uhd_image_builder.py b/fpga/usrp3/tools/scripts/uhd_image_builder.py deleted file mode 100755 index 7398b6e13..000000000 --- a/fpga/usrp3/tools/scripts/uhd_image_builder.py +++ /dev/null @@ -1,537 +0,0 @@ -#!/usr/bin/env python -""" -Copyright 2016-2017 Ettus Research -Copyright 2019 Ettus Research, A National Instrument Brand - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. -""" - -from __future__ import print_function -import argparse -import os -import re -import glob - -HEADER_TMPL = """///////////////////////////////////////////////////////// -// Auto-generated by uhd_image_builder.py! Any changes -// in this file will be overwritten the next time -// this script is run. -///////////////////////////////////////////////////////// -localparam NUM_CE = {num_ce}; -wire [NUM_CE*64-1:0] ce_flat_o_tdata, ce_flat_i_tdata; -wire [63:0] ce_o_tdata[0:NUM_CE-1], ce_i_tdata[0:NUM_CE-1]; -wire [NUM_CE-1:0] ce_o_tlast, ce_o_tvalid, ce_o_tready, ce_i_tlast, ce_i_tvalid, ce_i_tready; -wire [63:0] ce_debug[0:NUM_CE-1]; -// Flattern CE tdata arrays -genvar k; -generate - for (k = 0; k < NUM_CE; k = k + 1) begin - assign ce_o_tdata[k] = ce_flat_o_tdata[k*64+63:k*64]; - assign ce_flat_i_tdata[k*64+63:k*64] = ce_i_tdata[k]; - end -endgenerate -wire ce_clk = radio_clk; -wire ce_rst = radio_rst; -""" - -BLOCK_TMPL = """ -noc_block_{blockname} {blockparameters} {instname} ( - .bus_clk(bus_clk), .bus_rst(bus_rst), - .ce_clk({clock}_clk), .ce_rst({clock}_rst), - .i_tdata(ce_o_tdata[{n}]), .i_tlast(ce_o_tlast[{n}]), .i_tvalid(ce_o_tvalid[{n}]), .i_tready(ce_o_tready[{n}]), - .o_tdata(ce_i_tdata[{n}]), .o_tlast(ce_i_tlast[{n}]), .o_tvalid(ce_i_tvalid[{n}]), .o_tready(ce_i_tready[{n}]), - .debug(ce_debug[{n}]){extraports} -); -""" - -FILL_FIFO_TMPL = """ -// Fill remaining crossbar ports with loopback FIFOs -genvar n; -generate - for (n = {fifo_start}; n < NUM_CE; n = n + 1) begin - noc_block_axi_fifo_loopback inst_noc_block_axi_fifo_loopback ( - .bus_clk(bus_clk), .bus_rst(bus_rst), - .ce_clk(ce_clk), .ce_rst(ce_rst), - .i_tdata(ce_o_tdata[n]), .i_tlast(ce_o_tlast[n]), .i_tvalid(ce_o_tvalid[n]), .i_tready(ce_o_tready[n]), - .o_tdata(ce_i_tdata[n]), .o_tlast(ce_i_tlast[n]), .o_tvalid(ce_i_tvalid[n]), .o_tready(ce_i_tready[n]), - .debug(ce_debug[n]) - ); - end -endgenerate -""" - -# List of blocks that are part of our library but that do not take part -# in the process this tool provides -BLACKLIST = {'radio_core', 'axi_dma_fifo'} - -OOT_DIR_TMPL = """\nOOT_DIR = {oot_dir}\n""" -OOT_INC_TMPL = """include $(OOT_DIR)/Makefile.inc\n""" -OOT_SRCS_TMPL = """RFNOC_OOT_SRCS += {sources}\n""" -OOT_SRCS_FILE_HDR = """################################################## -# Include OOT makefiles -##################################################\n""" - - -def setup_parser(): - """ - Create argument parser - """ - parser = argparse.ArgumentParser( - description="Generate the NoC block instantiation file", - ) - parser.add_argument( - "-I", "--include-dir", - help="Path directory of the RFNoC Out-of-Tree module", - nargs='+', - default=None) - parser.add_argument( - "-y", "--yml", - help="YML file definition of onboard blocks\ - (overrides the 'block' positional arguments)", - default=None) - parser.add_argument( - "-m", "--max-num-blocks", type=int, - help="Maximum number of blocks (Max. Allowed for x310|x300: 10,\ - for e300: 14, for e320: 12, for n300: 11, \ - for n310/n320: 10)", - default=10) - parser.add_argument( - "--fill-with-fifos", - help="If the number of blocks provided was smaller than the max\ - number, fill the rest with FIFOs", - action="store_true") - parser.add_argument( - "-o", "--outfile", - help="Output /path/filename - By running this directive,\ - you won't build your IP", - default=None) - parser.add_argument( - "--auto-inst-src", - help="Advanced Usage: The Verilog source for the auto_inst file that " - "will be used instead of generating one automatically", - default=None) - parser.add_argument( - "-d", "--device", - help="Device to be programmed [x300, x310, e310, e320, n300, n310, n320]", - default="x310") - parser.add_argument( - "-t", "--target", - help="Build target - image type [X3X0_RFNOC_HG, X3X0_RFNOC_XG,\ - E310_RFNOC_sg3, E320_RFNOC_1G, N310_RFNOC_HG, ...]", - default=None) - parser.add_argument( - "-g", "--GUI", - help="Open Vivado GUI during the FPGA building process", - action="store_true") - parser.add_argument( - "-c", "--clean-all", - help="Cleans the IP before a new build", - action="store_true") - parser.add_argument( - "blocks", - help="List block names to instantiate.", - default="", - nargs='*', - ) - return parser - -def get_default_parameters(): - default = {"clock" : "ce", - "parameters" : None, - "extraports" : None} - return default - - -def parse_yml(ymlfile): - """ - Parse an input yaml file with a list of blocks and parameters! - """ - try: - import yaml - except ImportError: - print('[ERROR] Could not import yaml module') - exit(1) - - with open(ymlfile, 'r') as input_file: - data = yaml.load(input_file) - blocks = [] - params = [] - for val in data: - print(val['block']) - blocks.append(val['block']) - blockparams = get_default_parameters() - if "clock" in val: - blockparams["clock"] = val["clock"] - if "parameters" in val: - blockparams["parameters"] = val["parameters"] - if "extraports" in val: - blockparams["extraports"] = val["extraports"] - print(blockparams) - params.append(blockparams) - print(data) - return blocks, params - -def format_param_str(parameters): - """ - Take a single block parameter dictionary and format as a verilog string - """ - paramstr = "" - if parameters: - paramstrlist = [] - for key in parameters.keys(): - value = "" - if parameters[key] is not None: - value = parameters[key] - currstr = ".%s(%s)" % (str.upper(key), value) - paramstrlist.append(currstr) - paramstr = "#(%s)" % (", ".join(paramstrlist)) - return paramstr - -def format_port_str(extraports): - """ - Take a single dictionary and format as a verilog string representing extra block ports - """ - portstr = "" - if extraports: - portstrlist = [] - for key in extraports.keys(): - value = "" - if extraports[key] is not None: - value = extraports[key] - currstr = ".%s(%s)" % (key, value) - portstrlist.append(currstr) - portstr = ",\n %s" % (",\n ".join(portstrlist)) - return portstr - -def create_auto_inst(blocks, blockparams, max_num_blocks, fill_with_fifos=False): - """ - Returns the Verilog source for the auto_inst file. - """ - if len(blocks) == 0: - print("[GEN_RFNOC_INST ERROR] No blocks specified!") - exit(1) - if len(blocks) > max_num_blocks: - print("[GEN_RFNOC_INST ERROR] Trying to connect {} blocks, max is {}" - .format(len(blocks), max_num_blocks)) - exit(1) - num_ce = max_num_blocks - if not fill_with_fifos: - num_ce = len(blocks) - vfile = HEADER_TMPL.format(num_ce=num_ce) - blocks_in_blacklist = [block for block in blocks if block in BLACKLIST] - if len(blocks_in_blacklist): - print("[RFNoC ERROR]: The following blocks require special treatment and"\ - " can't be instantiated with this tool: ") - for element in blocks_in_blacklist: - print(" * ", element) - print("Remove them from the command and run the uhd_image_builder.py again.") - exit(0) - print("--Using the following blocks to generate image:") - block_count = {k: 0 for k in set(blocks)} - for i, (block, params) in enumerate(zip(blocks, blockparams)): - block_count[block] += 1 - instname = "inst_{}{}".format(block, "" \ - if block_count[block] == 1 else block_count[block]) - print(" * {}".format(block)) - vfile += BLOCK_TMPL.format(blockname=block, - blockparameters=format_param_str(params["parameters"]), - instname=instname, - n=i, - clock=params["clock"], - extraports=format_port_str(params["extraports"])) - if fill_with_fifos: - vfile += FILL_FIFO_TMPL.format(fifo_start=len(blocks)) - return vfile - -def file_generator(args, vfile): - """ - Takes the target device as an argument and, if no '-o' directive is given, - replaces the auto_ce file in the corresponding top folder. With the - presence of -o, it just generates a version of the verilog file which - is not intended to be build - """ - fpga_utils_path = get_scriptpath() - print("Adding CE instantiation file for '%s'" % args.target) - path_to_file = fpga_utils_path +'/../../top/' + device_dict(args.device.lower()) +\ - '/rfnoc_ce_auto_inst_' + args.device.lower() + '.v' - if args.outfile is None: - open(path_to_file, 'w').write(vfile) - else: - open(args.outfile, 'w').write(vfile) - -def append_re_line_sequence(filename, linepattern, newline): - """ Detects the re 'linepattern' in the file. After its last occurrence, - paste 'newline'. If the pattern does not exist, append the new line - to the file. Then, write. If the newline already exists, leaves the file - unchanged""" - oldfile = open(filename, 'r').read() - lines = re.findall(newline, oldfile, flags=re.MULTILINE) - if len(lines) != 0: - pass - else: - pattern_lines = re.findall(linepattern, oldfile, flags=re.MULTILINE) - if len(pattern_lines) == 0: - open(filename, 'a').write(newline) - return - last_line = pattern_lines[-1] - newfile = oldfile.replace(last_line, last_line + newline + '\n') - open(filename, 'w').write(newfile) - -def create_oot_include(device, include_dirs): - """ - Create the include file for OOT RFNoC sources - """ - oot_dir_list = [] - target_dir = device_dict(device.lower()) - dest_srcs_file = os.path.join(get_scriptpath(), '..', '..', 'top',\ - target_dir, 'Makefile.OOT.inc') - incfile = open(dest_srcs_file, 'w') - incfile.write(OOT_SRCS_FILE_HDR) - if include_dirs is not None: - for dirs in include_dirs: - currpath = os.path.abspath(str(dirs)) - if os.path.isdir(currpath) & (os.path.basename(currpath) == "rfnoc"): - # Case 1: Pointed directly to rfnoc directory - oot_path = currpath - elif os.path.isdir(os.path.join(currpath, 'rfnoc')): - # Case 2: Pointed to top level rfnoc module directory - oot_path = os.path.join(currpath, 'rfnoc') - elif os.path.isfile(os.path.join(currpath, 'Makefile.inc')): - # Case 3: Pointed to a random directory with a Makefile.inc - oot_path = currpath - else: - print('No RFNoC module found at ' + os.path.abspath(currpath)) - continue - if oot_path not in oot_dir_list: - oot_dir_list.append(oot_path) - named_path = os.path.join('$(BASE_DIR)', get_relative_path(get_basedir(), oot_path)) - incfile.write(OOT_DIR_TMPL.format(oot_dir=named_path)) - if os.path.isfile(os.path.join(oot_path, 'Makefile.inc')): - # Check for Makefile.inc - incfile.write(OOT_INC_TMPL) - elif os.path.isfile(os.path.join(oot_path, 'rfnoc', 'Makefile.inc')): - # Check for Makefile.inc - incfile.write(OOT_INC_TMPL) - elif os.path.isfile(os.path.join(oot_path, 'rfnoc', 'fpga-src', 'Makefile.srcs')): - # Legacy: Check for fpga-src/Makefile.srcs - # Read, then append to file - curr_srcs = open(os.path.join(oot_path, 'rfnoc', 'fpga-src', 'Makefile.srcs'), 'r').read() - curr_srcs = curr_srcs.replace('SOURCES_PATH', os.path.join(oot_path, 'rfnoc', 'fpga-src', '')) - incfile.write(OOT_SRCS_TMPL.format(sources=curr_srcs)) - else: - print('No valid makefile found at ' + os.path.abspath(currpath)) - continue - incfile.close() - -def append_item_into_file(device, include_dir): - """ - Basically the same as append_re_line_sequence function, but it does not - append anything when the input is not found - --- - Detects the re 'linepattern' in the file. After its last occurrence, - pastes the input string. If pattern doesn't exist - notifies and leaves the file unchanged - """ - def get_oot_srcs_list(include_dir): - """ - Pull the OOT sources out of the Makefile.srcs - """ - oot_srcs_file = os.path.join(include_dir, 'Makefile.srcs') - oot_srcs_list = readfile(oot_srcs_file) - return [w.replace('SOURCES_PATH', include_dir) for w in oot_srcs_list] - # Here we go - target_dir = device_dict(device.lower()) - if include_dir is not None: - for directory in include_dir: - dirs = os.path.join(directory, '') - checkdir_v(dirs) - dest_srcs_file = os.path.join(get_scriptpath(), '..', '..', 'top',\ - target_dir, 'Makefile.srcs') - oot_srcs_list = get_oot_srcs_list(dirs) - dest_srcs_list = readfile(dest_srcs_file) - prefixpattern = re.escape('$(addprefix ' + dirs + ', \\\n') - linepattern = re.escape('RFNOC_OOT_SRCS = \\\n') - oldfile = open(dest_srcs_file, 'r').read() - prefixlines = re.findall(prefixpattern, oldfile, flags=re.MULTILINE) - if len(prefixlines) == 0: - lines = re.findall(linepattern, oldfile, flags=re.MULTILINE) - if len(lines) == 0: - print("Pattern {} not found. Could not write `{}'" - .format(linepattern, oldfile)) - return - else: - last_line = lines[-1] - srcs = "".join(oot_srcs_list) - else: - last_line = prefixlines[-1] - srcs = "".join([ - item - for item in oot_srcs_list - if item not in dest_srcs_list - ]) - newfile = oldfile.replace(last_line, last_line + srcs) - open(dest_srcs_file, 'w').write(newfile) - -def compare(file1, file2): - """ - compares two files line by line, and returns the lines of first file that - were not found on the second. The returned is a tuple item that can be - accessed in the form of a list as tuple[0], where each line takes a - position on the list or in a string as tuple [1]. - """ - notinside = [] - with open(file1, 'r') as arg1: - with open(file2, 'r') as arg2: - text1 = arg1.readlines() - text2 = arg2.readlines() - for item in text1: - if item not in text2: - notinside.append(item) - return notinside - -def readfile(files): - """ - compares two files line by line, and returns the lines of first file that - were not found on the second. The returned is a tuple item that can be - accessed in the form of a list as tuple[0], where each line takes a - position on the list or in a string as tuple [1]. - """ - contents = [] - with open(files, 'r') as arg: - text = arg.readlines() - for item in text: - contents.append(item) - return contents - -def build(args): - " build " - cwd = get_scriptpath() - target_dir = device_dict(args.device.lower()) - build_dir = os.path.join(cwd, '..', '..', 'top', target_dir) - if os.path.isdir(build_dir): - print("changing temporarily working directory to {0}".\ - format(build_dir)) - os.chdir(build_dir) - make_cmd = ". ./setupenv.sh " - if args.clean_all: - make_cmd = make_cmd + "&& make cleanall " - make_cmd = make_cmd + "&& make " + dtarget(args) - if args.GUI: - make_cmd = make_cmd + " GUI=1" - # Wrap it into a bash call: - make_cmd = '/bin/bash -c "{0}"'.format(make_cmd) - ret_val = os.system(make_cmd) - os.chdir(cwd) - return ret_val - -def device_dict(args): - """ - helps selecting the device building folder based on the targeted device - """ - build_dir = { - 'x300':'x300', - 'x310':'x300', - 'e300':'e31x', - 'e310':'e31x', - 'e320':'e320', - 'n300':'n3xx', - 'n310':'n3xx', - 'n320':'n3xx' - } - return build_dir[args] - -def dtarget(args): - """ - If no target specified, selects the default building target based on the - targeted device - """ - if args.target is None: - default_trgt = { - 'x300':'X300_RFNOC_HG', - 'x310':'X310_RFNOC_HG', - 'e310':'E310_SG3_RFNOC', - 'e320':'E320_RFNOC_1G', - 'n300':'N300_RFNOC_HG', - 'n310':'N310_RFNOC_HG', - 'n320':'N320_RFNOC_XG', - } - return default_trgt[args.device.lower()] - else: - return args.target - -def checkdir_v(include_dir): - """ - Checks the existance of verilog files in the given include dir - """ - nfiles = glob.glob(os.path.join(include_dir,'')+'*.v') - if len(nfiles) == 0: - print('[ERROR] No verilog files found in the given directory') - exit(0) - else: - print('Verilog sources found!') - return - -def get_scriptpath(): - """ - returns the absolute path where a script is located - """ - return os.path.dirname(os.path.realpath(__file__)) - -def get_basedir(): - """ - returns the base directory (BASE_DIR) used in rfnoc build process - """ - return os.path.abspath(os.path.join(get_scriptpath(), '..', '..', 'top')) - -def get_relative_path(base, target): - """ - Find the relative path (including going "up" directories) from base to target - """ - basedir = os.path.abspath(base) - prefix = os.path.commonprefix([basedir, os.path.abspath(target)]) - path_tail = os.path.relpath(os.path.abspath(target), prefix) - total_path = path_tail - if prefix != "": - while basedir != os.path.abspath(prefix): - basedir = os.path.dirname(basedir) - total_path = os.path.join('..', total_path) - return total_path - else: - print("Could not determine relative path") - return path_tail - -def main(): - " Go, go, go! " - args = setup_parser().parse_args() - if args.yml: - print("Using yml file. Ignoring command line blocks arguments") - blocks, params = parse_yml(args.yml) - else: - blocks = args.blocks - params = [get_default_parameters()]*len(blocks) - if args.auto_inst_src is None: - vfile = create_auto_inst(blocks, params, args.max_num_blocks, args.fill_with_fifos) - else: - vfile = open(args.auto_inst_src, 'r').read() - file_generator(args, vfile) - create_oot_include(args.device, args.include_dir) - if args.outfile is None: - return build(args) - else: - print("Instantiation file generated at {}".\ - format(args.outfile)) - return 0 - -if __name__ == "__main__": - exit(main()) diff --git a/fpga/usrp3/tools/scripts/uhd_image_builder_gui.py b/fpga/usrp3/tools/scripts/uhd_image_builder_gui.py deleted file mode 100755 index 4d14cd256..000000000 --- a/fpga/usrp3/tools/scripts/uhd_image_builder_gui.py +++ /dev/null @@ -1,656 +0,0 @@ -#!/usr/bin/env python -""" -Copyright 2016-2018 Ettus Research - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. -""" - -from __future__ import print_function -import os -import re -import sys -import signal -import threading -import xml.etree.ElementTree as ET -from PyQt5 import (QtGui, - QtCore, - QtWidgets) -from PyQt5.QtWidgets import QGridLayout -from PyQt5.QtCore import (pyqtSlot, - Qt, - QModelIndex) -import uhd_image_builder - -signal.signal(signal.SIGINT, signal.SIG_DFL) - -class MainWindow(QtWidgets.QWidget): - """ - UHD_IMAGE_BUILDER - """ - # pylint: disable=too-many-instance-attributes - - def __init__(self): - super(MainWindow, self).__init__() - ################################################## - # Initial Values - ################################################## - self.target = 'x300' - self.device = 'x310' - self.build_target = 'X310_RFNOC_HG' - self.oot_dirs = [] - self.max_allowed_blocks = 10 - self.cmd_dict = {"target": '-t {}'.format(self.build_target), - "device": '-d {}'.format(self.device), - "include": '', - "fill_fifos": '', - "viv_gui": '', - "cleanall": '', - "show_file": ''} - self.cmd_name = ['./uhd_image_builder.py', ] - self.cmd_prefix = list(self.cmd_name) - self.instantiation_file = os.path.join(uhd_image_builder.get_scriptpath(), - '..', '..', 'top', self.target, - 'rfnoc_ce_auto_inst_' + self.device.lower() + - '.v') - - # List of blocks that are part of our library but that do not take place - # on the process this tool provides - self.blacklist = ['noc_block_radio_core', 'noc_block_axi_dma_fifo', 'noc_block_pfb'] - self.lock = threading.Lock() - self.init_gui() - - def init_gui(self): - """ - Initializes GUI init values and constants - """ - # pylint: disable=too-many-statements - - ettus_sources = os.path.join(uhd_image_builder.get_scriptpath(), '..', '..', 'lib',\ - 'rfnoc', 'Makefile.srcs') - ################################################## - # Grid Layout - ################################################## - grid = QGridLayout() - grid.setSpacing(15) - ################################################## - # Buttons - ################################################## - oot_btn = QtWidgets.QPushButton('Add OOT Blocks', self) - oot_btn.setToolTip('Add your custom Out-of-tree blocks') - grid.addWidget(oot_btn, 9, 0) - from_grc_btn = QtWidgets.QPushButton('Import from GRC', self) - grid.addWidget(from_grc_btn, 9, 2) - show_file_btn = QtWidgets.QPushButton('Show instantiation File', self) - grid.addWidget(show_file_btn, 9, 1) - add_btn = QtWidgets.QPushButton('>>', self) - grid.addWidget(add_btn, 2, 2) - rem_btn = QtWidgets.QPushButton('<<', self) - grid.addWidget(rem_btn, 3, 2) - self.gen_bit_btn = QtWidgets.QPushButton('Generate .bit file', self) - grid.addWidget(self.gen_bit_btn, 9, 3) - - ################################################## - # Checkbox - ################################################## - self.fill_with_fifos = QtWidgets.QCheckBox('Fill with FIFOs', self) - self.viv_gui = QtWidgets.QCheckBox('Open Vivado GUI', self) - self.cleanall = QtWidgets.QCheckBox('Clean IP', self) - grid.addWidget(self.fill_with_fifos, 5, 2) - grid.addWidget(self.viv_gui, 6, 2) - grid.addWidget(self.cleanall, 7, 2) - - ################################################## - # uhd_image_builder command display - ################################################## - label_cmd_display = QtWidgets.QLabel(self) - label_cmd_display.setText("uhd_image_builder command:") - label_cmd_display.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) - label_cmd_display.setStyleSheet(" QLabel {font-weight: bold; color: black}") - grid.addWidget(label_cmd_display, 10, 0) - self.cmd_display = QtWidgets.QTextEdit(self) - self.cmd_display.setMaximumHeight(label_cmd_display.sizeHint().height() * 3) - self.cmd_display.setReadOnly(True) - self.cmd_display.setText("".join(self.cmd_name)) - grid.addWidget(self.cmd_display, 10, 1, 1, 3) - - ################################################## - # uhd_image_builder target help display - ################################################## - self.help_display = QtWidgets.QLabel(self) - grid.addWidget(self.help_display, 11, 1, 1, 3) - self.help_display.setWordWrap(True) - help_description = QtWidgets.QLabel(self) - grid.addWidget(help_description, 11, 0) - help_description.setText("Target description: ") - help_description.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) - help_description.setStyleSheet(" QLabel {font-weight: bold; color: black}") - - ################################################## - # Panels - QTreeModels - ################################################## - ### Far-left Panel: Build targets - self.targets = QtWidgets.QTreeView(self) - self.targets.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) - self.model_targets = QtGui.QStandardItemModel(self) - self.model_targets.setHorizontalHeaderItem(0, QtGui.QStandardItem("Select build target")) - self.targets.setModel(self.model_targets) - self.populate_target('x300') - self.populate_target('e300') - self.populate_target('e320') - self.populate_target('n3xx') - grid.addWidget(self.targets, 0, 0, 8, 1) - - ### Central Panel: Available blocks - ### Create tree to categorize Ettus Block and OOT Blocks in different lists - self.blocks_available = QtWidgets.QTreeView(self) - self.blocks_available.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) - self.blocks_available.setContextMenuPolicy(Qt.CustomContextMenu) - ettus_blocks = QtGui.QStandardItem("Ettus-provided Blocks") - ettus_blocks.setEnabled(False) - ettus_blocks.setForeground(Qt.black) - self.populate_list(ettus_blocks, ettus_sources) - self.oot = QtGui.QStandardItem("OOT Blocks for X300 devices") - self.oot.setEnabled(False) - self.oot.setForeground(Qt.black) - self.refresh_oot_dirs() - self.model_blocks_available = QtGui.QStandardItemModel(self) - self.model_blocks_available.appendRow(ettus_blocks) - self.model_blocks_available.appendRow(self.oot) - self.model_blocks_available.setHorizontalHeaderItem( - 0, QtGui.QStandardItem("List of blocks available") - ) - self.blocks_available.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) - self.blocks_available.setModel(self.model_blocks_available) - grid.addWidget(self.blocks_available, 0, 1, 8, 1) - - ### Far-right Panel: Blocks in current design - self.blocks_in_design = QtWidgets.QTreeView(self) - self.blocks_in_design.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) - self.model_in_design = QtGui.QStandardItemModel(self) - self.model_in_design.setHorizontalHeaderItem( - 0, QtGui.QStandardItem("Blocks in current design")) - self.blocks_in_design.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) - self.blocks_in_design.setModel(self.model_in_design) - grid.addWidget(self.blocks_in_design, 0, 3, 8, 1) - - ################################################## - # Informative Labels - ################################################## - block_num_hdr = QtWidgets.QLabel(self) - block_num_hdr.setText("Blocks in current design") - block_num_hdr.setStyleSheet(" QLabel {font-weight: bold; color: black}") - block_num_hdr.setAlignment(QtCore.Qt.AlignHCenter) - grid.addWidget(block_num_hdr, 0, 2) - self.block_num = QtWidgets.QLabel(self) - self.block_num.setText("-") - self.block_num.setAlignment(QtCore.Qt.AlignHCenter) - grid.addWidget(self.block_num, 1, 2) - self.block_num.setStyleSheet(" QLabel {color: green}") - self.generating_bitstream = QtWidgets.QLabel(self) - self.generating_bitstream.setText("") - self.generating_bitstream.setAlignment(QtCore.Qt.AlignHCenter) - grid.addWidget(self.generating_bitstream, 11, 0, 1, 5) - self.generating_bitstream.setStyleSheet(" QLabel {font-weight: bold; color: black}") - - ################################################## - # Connection of the buttons with their signals - ################################################## - self.fill_with_fifos.clicked.connect(self.fill_slot) - self.fill_with_fifos.clicked.connect(self.cmd_display_slot) - self.viv_gui.clicked.connect(self.viv_gui_slot) - self.viv_gui.clicked.connect(self.cmd_display_slot) - self.cleanall.clicked.connect(self.cleanall_slot) - self.cleanall.clicked.connect(self.cmd_display_slot) - oot_btn.clicked.connect(self.file_dialog) - from_grc_btn.clicked.connect(self.blocks_to_add_slot) - from_grc_btn.clicked.connect(self.cmd_display_slot) - from_grc_btn.clicked.connect(self.file_grc_dialog) - add_btn.clicked.connect(self.add_to_design) - add_btn.clicked.connect(self.blocks_to_add_slot) - add_btn.clicked.connect(self.check_blk_num) - add_btn.clicked.connect(self.cmd_display_slot) - rem_btn.clicked.connect(self.remove_from_design) - rem_btn.clicked.connect(self.blocks_to_add_slot) - rem_btn.clicked.connect(self.cmd_display_slot) - show_file_btn.clicked.connect(self.show_file) - show_file_btn.clicked.connect(self.cmd_display_slot) - show_file_btn.clicked.connect(self.run_command) - self.gen_bit_btn.clicked.connect(self.generate_bit) - self.gen_bit_btn.clicked.connect(self.cmd_display_slot) - self.gen_bit_btn.clicked.connect(self.run_command) - self.targets.clicked.connect(self.ootlist) - self.targets.clicked.connect(self.set_target_and_device) - self.targets.clicked.connect(self.cmd_display_slot) - self.targets.clicked.connect(self.check_blk_num) - self.blocks_available.doubleClicked.connect(self.add_to_design) - self.blocks_available.doubleClicked.connect(self.blocks_to_add_slot) - self.blocks_available.doubleClicked.connect(self.check_blk_num) - self.blocks_available.doubleClicked.connect(self.cmd_display_slot) - self.blocks_in_design.doubleClicked.connect(self.remove_from_design) - self.blocks_in_design.doubleClicked.connect(self.blocks_to_add_slot) - self.blocks_in_design.doubleClicked.connect(self.cmd_display_slot) - - ################################################## - # Set a default size based on screen geometry - ################################################## - screen_size = QtWidgets.QDesktopWidget().screenGeometry(-1) - self.resize(screen_size.width()/1.4, screen_size.height()/1.7) - self.setWindowTitle("uhd_image_builder.py GUI") - self.setLayout(grid) - self.show() - - ################################################## - # Slots and functions/actions - ################################################## - @pyqtSlot() - def blocks_to_add_slot(self): - """ - Retrieves a list of the blocks in design to be displayed in TextEdit - """ - availables = [] - blocks = [] - availables = self.iter_tree(self.model_blocks_available, availables) - blk_count = self.model_in_design.rowCount() - self.block_num.setText("{}/{}".format(blk_count, - self.max_allowed_blocks)) - for i in range(blk_count): - blocks.append(self.blocks_in_design.model().data( - self.blocks_in_design.model().index(i, 0))) - self.cmd_prefix = self.cmd_name + blocks - - @pyqtSlot() - def check_blk_num(self): - """ - Checks the amount of blocks in the design pannel - """ - blk_count = self.model_in_design.rowCount() - if blk_count > self.max_allowed_blocks: - self.block_num.setStyleSheet(" QLabel {font-weight:bold; color: red}") - self.show_too_many_blocks_warning(blk_count) - - @pyqtSlot() - def fill_slot(self): - """ - Populates 'fill_fifos' value into the command dictionary - """ - if self.fill_with_fifos.isChecked(): - self.cmd_dict["fill_fifos"] = '--fill-with-fifos' - else: - self.cmd_dict["fill_fifos"] = '' - - @pyqtSlot() - def viv_gui_slot(self): - """ - Populates 'viv_gui' value into the command dictionary - """ - if self.viv_gui.isChecked(): - self.cmd_dict["viv_gui"] = '-g' - else: - self.cmd_dict["viv_gui"] = '' - - @pyqtSlot() - def cleanall_slot(self): - """ - Populates 'cleanall' value into the command dictionary - """ - if self.cleanall.isChecked(): - self.cmd_dict["cleanall"] = '-c' - else: - self.cmd_dict["cleanall"] = '' - - @pyqtSlot() - def cmd_display_slot(self): - """ - Displays the command to be run in a QTextEdit in realtime - """ - text = [" ".join(self.cmd_prefix),] - for value in self.cmd_dict.values(): - if value is not '': - text.append(value) - self.cmd_display.setText(" ".join(text)) - - @pyqtSlot() - def add_to_design(self): - """ - Adds blocks from the 'available' pannel to the list to be added - into the design - """ - indexes = self.blocks_available.selectedIndexes() - for index in indexes: - word = self.blocks_available.model().data(index) - element = QtGui.QStandardItem(word) - if word is not None: - self.model_in_design.appendRow(element) - - @pyqtSlot() - def remove_from_design(self): - """ - Removes blocks from the list that is to be added into the design - """ - indexes = self.blocks_in_design.selectedIndexes() - for index in indexes: - self.model_in_design.removeRow(index.row()) - # Edit Informative Label formatting - blk_count = self.model_in_design.rowCount() - if blk_count <= self.max_allowed_blocks: - self.block_num.setStyleSheet(" QLabel {color: green}") - - @pyqtSlot() - def show_file(self): - """ - Show the rfnoc_ce_auto_inst file in the default text editor - """ - self.cmd_dict['show_file'] = '-o {}'.format(self.instantiation_file) - - @pyqtSlot() - def generate_bit(self): - """ - Runs the FPGA .bit generation command - """ - self.cmd_dict['show_file'] = '' - - @pyqtSlot() - def run_command(self): - """ - Executes the uhd_image_builder command based on user options - """ - if self.check_no_blocks() and self.check_blk_not_in_sources(): - process = threading.Thread(target=self.generate_bitstream) - process.start() - if self.cmd_dict['show_file'] is not '': - os.system("xdg-open " + self.instantiation_file) - - @pyqtSlot() - def set_target_and_device(self): - """ - Populates the 'target' and 'device' values of the command directory - and the device dependent max_allowed_blocks in display - """ - self.cmd_dict['target'] = '-t {}'.format(self.build_target) - self.cmd_dict['device'] = '-d {}'.format(self.device) - blk_count = self.model_in_design.rowCount() - self.block_num.setText("{}/{}".format(blk_count, - self.max_allowed_blocks)) - self.instantiation_file = os.path.join(uhd_image_builder.get_scriptpath(), - '..', '..', 'top', self.target, - 'rfnoc_ce_auto_inst_' + self.device.lower() + - '.v') - - @pyqtSlot() - def ootlist(self): - """ - Lists the Out-of-tree module blocks - """ - index = self.targets.currentIndex() - self.build_target = str(self.targets.model().data(index)) - self.device = self.build_target[:4] - if self.device == 'X310' or self.device == 'X300': - self.target = 'x300' - self.max_allowed_blocks = 10 - elif self.device == 'E310': - self.target = 'e300' - self.max_allowed_blocks = 14 - elif self.device == 'E320': - self.target = 'e320' - self.max_allowed_blocks = 12 - elif self.device == 'N300': - self.target = 'n3xx' - self.max_allowed_blocks = 11 - elif self.device == 'N310' or self.device == 'N320': - self.target = 'n3xx' - self.max_allowed_blocks = 10 - oot_sources = os.path.join(uhd_image_builder.get_scriptpath(), '..', '..', 'top',\ - self.target, 'Makefile.srcs') - self.show_list(self.oot, self.target, oot_sources) - - # Show the help string for a selected target - selected_makefile = os.path.join(uhd_image_builder.get_scriptpath(), - '..', '..', 'top', self.target, 'Makefile') - pattern = "^\#\S*{}.*".format(self.build_target) - with open(selected_makefile) as fil: - help_string = re.findall(pattern, fil.read(), re.MULTILINE)[0].replace("##","") - self.help_display.setText(help_string) - - @pyqtSlot() - def file_dialog(self): - """ - Opens a dialog window to add manually the Out-of-tree module blocks - """ - append_directory = [] - startpath = os.path.join(uhd_image_builder.get_scriptpath(), '..', '..', '..', '..') - new_oot = str(QtWidgets.QFileDialog.getExistingDirectory(self, 'RFNoC Out of Tree Directory', startpath)) - if len(new_oot) > 0: - self.oot_dirs.append(new_oot) - uhd_image_builder.create_oot_include(self.device, self.oot_dirs) - self.refresh_oot_dirs() - - @pyqtSlot() - def file_grc_dialog(self): - """ - Opens a dialog window to add manually the GRC description file, from where - the RFNoC blocks will be parsed and added directly into the "Design" pannel - """ - filename = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', '/home/')[0] - if len(filename) > 0: - self.grc_populate_list(self.model_in_design, filename) - self.set_target_and_device() - self.blocks_to_add_slot() - self.cmd_display_slot() - - def check_no_blocks(self): - """ - Checks if there are no blocks in the design pannel. Needs to be a - different slot because triggers from clicking signals from pannels - would be superfluous - """ - blk_count = self.model_in_design.rowCount() - if blk_count == 0: - self.show_no_blocks_warning() - return False - return True - - def show_no_srcs_warning(self, block_to_add): - """ - Shows a warning message window when no sources are found for the blocks that - are in the design pannel - """ - # Create Warning message window - msg = QtWidgets.QMessageBox() - msg.setIcon(QtWidgets.QMessageBox.Warning) - msg.setText("The following blocks are in your design but their sources"\ - " have not been added: \n\n {0}. \n\nPlease be sure of adding them"\ - "before continuing. Would you like to add them now?"\ - "".format(block_to_add)) - msg.setWindowTitle("No sources for design") - yes_btn = msg.addButton("Yes", QtWidgets.QMessageBox.YesRole) - no_btn = msg.addButton("No", QtWidgets.QMessageBox.NoRole) - msg.exec_() - if msg.clickedButton() == yes_btn: - self.file_dialog() - return False - elif msg.clickedButton() == no_btn: - return True - - @staticmethod - def show_no_blocks_warning(): - """ - Shows a warning message window when no blocks are found in the 'design' pannel - """ - # Create Warning message window - msg = QtWidgets.QMessageBox() - msg.setIcon(QtWidgets.QMessageBox.Warning) - msg.setText("There are no Blocks in the current design") - msg.exec_() - - def show_too_many_blocks_warning(self, number_of_blocks): - """ - Shows a warning message window when too many blocks are found in the 'design' pannel - """ - # Create Warning message window - msg = QtWidgets.QMessageBox() - msg.setIcon(QtWidgets.QMessageBox.Warning) - msg.setText("You added {} blocks while the maximum allowed blocks for"\ - " a {} device is {}. Please remove some of the blocks to "\ - "continue with the design".format(number_of_blocks, - self.device, self.max_allowed_blocks)) - msg.exec_() - - def iter_tree(self, model, output, parent=QModelIndex()): - """ - Iterates over the Index tree - """ - for i in range(model.rowCount(parent)): - index = model.index(i, 0, parent) - item = model.data(index) - output.append(str(item)) - if model.hasChildren(index): - self.iter_tree(model, output, index) - return output - - def show_list(self, parent, target, files): - """ - Shows the Out-of-tree blocks that are available for a given device - """ - parent.setText('OOT Blocks for {} devices'.format(target.upper())) - self.refresh_oot_dirs() - - def populate_list(self, parent, files, clear=True): - """ - Populates the pannels with the blocks that are listed in the Makefile.srcs - of our library - """ - # Clean the list before populating it again - if (clear): - parent.removeRows(0, parent.rowCount()) - suffix = '.v \\\n' - with open(files) as fil: - blocks = fil.readlines() - for element in blocks: - if element.endswith(suffix) and 'noc_block' in element: - element = element[:-len(suffix)] - if element not in self.blacklist: - block = QtGui.QStandardItem(element.partition('noc_block_')[2]) - parent.appendRow(block) - - @staticmethod - def show_not_xml_warning(): - """ - Shows a warning message window when no blocks are found in the 'design' pannel - """ - # Create Warning message window - msg = QtWidgets.QMessageBox() - msg.setIcon(QtWidgets.QMessageBox.Warning) - msg.setText("[ParseError]: The chosen file is not XML formatted") - msg.exec_() - - def grc_populate_list(self, parent, files): - """ - Populates the 'Design' list with the RFNoC blocks found in a GRC file - """ - try: - tree = ET.parse(files) - root = tree.getroot() - for blocks in root.iter('block'): - for param in blocks.iter('param'): - for key in param.iter('key'): - if 'fpga_module_name' in key.text: - if param.findtext('value') in self.blacklist: - continue - block = QtGui.QStandardItem(param.findtext('value').\ - partition('noc_block_')[2]) - parent.appendRow(block) - except ET.ParseError: - self.show_not_xml_warning() - return - - def refresh_oot_dirs(self): - """ - Populates the OOT directory list from the OOT include file - """ - oot_include = os.path.join(uhd_image_builder.get_scriptpath(), '..', '..', 'top',\ - self.target, 'Makefile.OOT.inc') - dir_list = [] - with open(oot_include, 'r') as fil: - text = fil.readlines() - for lines in text: - lines = lines.partition('$(BASE_DIR)/') - if (lines[1] == '$(BASE_DIR)/'): - relpath = lines[2].replace('\n', '') - ootpath = os.path.abspath(os.path.join(uhd_image_builder.get_scriptpath(), '..', '..', 'top', relpath)) - dir_list.append(ootpath) - if (len(dir_list) == 0): - self.oot.removeRows(0, self.oot.rowCount()) - self.cmd_dict["include"] = '' - else: - self.oot_dirs = dir_list - self.cmd_dict["include"] = '-I {}'.format(' '.join(self.oot_dirs)) - for (ii, oot) in enumerate(dir_list): - self.populate_list(self.oot, os.path.join(oot, 'fpga-src', 'Makefile.srcs'), clear=ii==0) - - def populate_target(self, selected_target): - """ - Parses the Makefile available and lists the build targets into the left pannel - """ - pattern = "^(?!\#)^\S*_RFNOC[^:]*" - build_targets = os.path.join(uhd_image_builder.get_scriptpath(), '..', '..', 'top', - selected_target, 'Makefile') - with open(build_targets) as fil: - targets = re.findall(pattern, fil.read(), re.MULTILINE) - for target in targets: - self.model_targets.appendRow(QtGui.QStandardItem(target)) - - def check_blk_not_in_sources(self): - """ - Checks if a block added from GRC flowgraph is not yet in the sources - list - """ - availables = [] - notin = [] - availables = self.iter_tree(self.model_blocks_available, availables) - for i in range(self.model_in_design.rowCount()): - block_to_add = self.blocks_in_design.model().data( - self.blocks_in_design.model().index(i, 0)) - if str(block_to_add) not in availables: - notin.append(str(block_to_add)) - if len(notin) > 0: - self.show_no_srcs_warning(notin) - return False - return True - - def generate_bitstream(self): - """ - Runs the bitstream generation command in a separate thread - """ - self.lock.acquire() - self.gen_bit_btn.setEnabled(False) - command = self.cmd_display.toPlainText() - self.generating_bitstream.setText( - "[Generating BitStream]: The FPGA is currently being generated" + \ - " with the blocks of the current design. See the terminal window" + \ - " for further compilation details") - os.system(command) - self.lock.release() - self.gen_bit_btn.setEnabled(True) - self.generating_bitstream.setText("") - -def main(): - """ - Main GUI method - """ - app = QtWidgets.QApplication(sys.argv) - _window = MainWindow() - sys.exit(app.exec_()) - -if __name__ == '__main__': - main() |