diff options
Diffstat (limited to 'host/lib/transport/nirio')
18 files changed, 2963 insertions, 0 deletions
diff --git a/host/lib/transport/nirio/CMakeLists.txt b/host/lib/transport/nirio/CMakeLists.txt new file mode 100644 index 000000000..6a33da6c5 --- /dev/null +++ b/host/lib/transport/nirio/CMakeLists.txt @@ -0,0 +1,48 @@ +# +# Copyright 2013-2014 Ettus Research LLC +# +# 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/>. +# + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +######################################################################## +# Include subdirectories (different than add) +######################################################################## +INCLUDE_SUBDIRECTORY(lvbitx) +INCLUDE_SUBDIRECTORY(rpc) + +######################################################################## +# Append to the list of sources for lib uhd +######################################################################## + +LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/nifpga_lvbitx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/niusrprio_session.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/niriok_proxy.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/nirio_resource_manager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/status.cpp +) + +IF(WIN32) + LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_win.cpp) +ELSE(WIN32) + IF(APPLE) + LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_macos.cpp) + ELSE(APPLE) + LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_SOURCE_DIR}/nirio_driver_iface_linux.cpp) + ENDIF(APPLE) +ENDIF(WIN32) diff --git a/host/lib/transport/nirio/lvbitx/CMakeLists.txt b/host/lib/transport/nirio/lvbitx/CMakeLists.txt new file mode 100644 index 000000000..35cfaa456 --- /dev/null +++ b/host/lib/transport/nirio/lvbitx/CMakeLists.txt @@ -0,0 +1,65 @@ +# +# Copyright 2013 Ettus Research LLC +# +# 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/>. +# + +MACRO(LIBUHD_LVBITX_GEN_SOURCE_AND_BITSTREAM lvbitx binfile) + GET_FILENAME_COMPONENT(lvbitxprefix ${lvbitx} NAME_WE) + + IF( ${binfile} STREQUAL "OFF" ) + SET( GEN_OPTIONS ) + MESSAGE( STATUS " Using ${lvbitx} for codegen" ) + ELSE( ${binfile} STREQUAL "OFF" ) + SET( GEN_OPTIONS --merge-bin=${CMAKE_SOURCE_DIR}/../binaries/${binfile} --output-lvbitx-path=${CMAKE_SOURCE_DIR}/../binaries ) + MESSAGE( STATUS " Merging ${lvbitx} with ${binfile} for codegen" ) + ENDIF( ${binfile} STREQUAL "OFF" ) + + SET(OUTPUT_PATH_OPT --output-src-path=${CMAKE_CURRENT_BINARY_DIR}) + SET(IMAGES_PATH_OPT --uhd-images-path=${FPGA_IMAGES_DIR}) + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${lvbitxprefix}_lvbitx.hpp + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${lvbitxprefix}_lvbitx.cpp + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/process-lvbitx.py + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/template_lvbitx.hpp + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/template_lvbitx.cpp + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${lvbitx} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/process-lvbitx.py ${OUTPUT_PATH_OPT} ${IMAGES_PATH_OPT} ${GEN_OPTIONS} ${CMAKE_CURRENT_SOURCE_DIR}/${lvbitx} + COMMENT "Generating ${CMAKE_CURRENT_BINARY_DIR}/${lvbitxprefix}_lvbitx.cpp" + ) + + #make libuhd depend on the output file + LIBUHD_APPEND_SOURCES(${CMAKE_CURRENT_BINARY_DIR}/${lvbitxprefix}_lvbitx.cpp) +ENDMACRO(LIBUHD_LVBITX_GEN_SOURCE_AND_BITSTREAM) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + +######################################################################## +# Generation code +######################################################################## + +MESSAGE(STATUS "") +MESSAGE(STATUS "Processing NI-RIO FPGA LVBITX Bitstreams...") + +FILE(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/share/uhd/images default_images_dir) +SET( FPGA_IMAGES_DIR ${default_images_dir} CACHE STRING "Path to installed FPGA image files." ) +OPTION( FPGA_IMAGES_DIR "Path to installed FPGA image files." "" ) +MESSAGE( STATUS " LVBITX install directory: ${FPGA_IMAGES_DIR}" ) + +# X300 Stuff +LIBUHD_LVBITX_GEN_SOURCE_AND_BITSTREAM(x300.lvbitx_base OFF) + +# X310 Stuff +LIBUHD_LVBITX_GEN_SOURCE_AND_BITSTREAM(x310.lvbitx_base OFF) diff --git a/host/lib/transport/nirio/lvbitx/process-lvbitx.py b/host/lib/transport/nirio/lvbitx/process-lvbitx.py new file mode 100755 index 000000000..a3d88d0bb --- /dev/null +++ b/host/lib/transport/nirio/lvbitx/process-lvbitx.py @@ -0,0 +1,185 @@ +#!/usr/bin/python +# +# Copyright 2013-2014 Ettus Research LLC +# +# 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 xml.etree import ElementTree +from collections import namedtuple +import optparse +import base64 +import hashlib +import os +import sys + +# Parse options +parser = optparse.OptionParser() +parser.add_option("--uhd-images-path", type="string", dest="uhd_images_path", help="Install location for UHD images", default='') +parser.add_option("--merge-bin", type="string", dest="merge_bin", help="Path to bin file that needs to be merged with the LVBITX before exporting", default=None) +parser.add_option("--output-bin", action="store_true", dest="output_bin", help="Generate a binary FPGA programming bitstream file", default=False) +parser.add_option("--output-lvbitx-path", type="string", dest="output_lvbitx_path", help="Output path for autogenerated LVBITX file", default=None) +parser.add_option("--output-src-path", type="string", dest="output_src_path", help="Output path for autogenerated src file", default=None) +(options, args) = parser.parse_args() + +# Args +if (len(args) < 1): + print 'ERROR: Please specify the input LVBITX file name' + sys.exit(1) + +lvbitx_filename = args[0] +input_filename = os.path.abspath(lvbitx_filename) +autogen_src_path = os.path.abspath(options.output_src_path) if (options.output_src_path is not None) else os.path.dirname(input_filename) +class_name = os.path.splitext(os.path.basename(input_filename))[0] + +if (not os.path.isfile(input_filename)): + print 'ERROR: FPGA File ' + input_filename + ' could not be accessed or is not a file.' + sys.exit(1) +if (options.merge_bin is not None and not os.path.isfile(os.path.abspath(options.merge_bin))): + print 'ERROR: FPGA Bin File ' + options.merge_bin + ' could not be accessed or is not a file.' + sys.exit(1) +if (not os.path.exists(autogen_src_path)): + print 'ERROR: Output path ' + autogen_src_path + ' could not be accessed.' + sys.exit(1) +if (options.output_lvbitx_path is not None and input_filename == os.path.join(autogen_src_path, class_name + '.lvbitx')): + print 'ERROR: Input and output LVBITX files were the same. Choose a difference input file or output path.' + sys.exit(1) + +# Get XML Tree Node +tree = ElementTree.parse(input_filename) +root = tree.getroot() +codegen_transform = {} + +# General info +codegen_transform['autogen_msg'] = '// Auto-generated file: DO NOT EDIT!\n// Generated from a LabVIEW FPGA LVBITX image using "process-lvbitx.py"' +codegen_transform['lvbitx_search_paths'] = options.uhd_images_path.replace('\\', '\\\\') +codegen_transform['lvbitx_classname'] = class_name +codegen_transform['lvbitx_classname_u'] = class_name.upper() +bitstream_version = root.find('BitstreamVersion').text + +# Enumerate registers (controls and indicators) +register_list = root.find('VI').find('RegisterList') + +reg_init_seq = '' +control_list = '' +indicator_list = '' +control_idx = 0 +indicator_idx = 0 +for register in register_list.findall('Register'): + reg_type = 'INDICATOR' if (register.find('Indicator').text.lower() == 'true') else 'CONTROL' + reg_name = '\"' + register.find('Name').text + '\"' + + if (reg_type == 'INDICATOR'): + indicator_list += '\n ' + reg_name + ',' + idx = indicator_idx + indicator_idx += 1 + else: + control_list += '\n ' + reg_name + ',' + idx = control_idx + control_idx += 1 + + reg_init_seq += '\n vtr.push_back(nirio_register_info_t(' + reg_init_seq += hex(int(register.find('Offset').text)) + ', ' + reg_init_seq += reg_type + 'S[' + str(idx) + '], ' + reg_init_seq += reg_type + reg_init_seq += ')); //' + reg_name + + +codegen_transform['register_init'] = reg_init_seq +codegen_transform['control_list'] = control_list +codegen_transform['indicator_list'] = indicator_list + +# Enumerate FIFOs +nifpga_metadata = root.find('Project').find('CompilationResultsTree').find('CompilationResults').find('NiFpga') +dma_channel_list = nifpga_metadata.find('DmaChannelAllocationList') +reg_block_list = nifpga_metadata.find('RegisterBlockList') + +fifo_init_seq = '' +out_fifo_list = '' +in_fifo_list = '' +out_fifo_idx = 0 +in_fifo_idx = 0 +for dma_channel in dma_channel_list: + fifo_name = '\"' + dma_channel.attrib['name'] + '\"' + direction = 'OUTPUT_FIFO' if (dma_channel.find('Direction').text == 'HostToTarget') else 'INPUT_FIFO' + for reg_block in reg_block_list.findall('RegisterBlock'): + if (reg_block.attrib['name'] == dma_channel.find('BaseAddressTag').text): + base_addr = reg_block.find('Offset').text + break + + if (direction == 'OUTPUT_FIFO'): + out_fifo_list += '\n ' + fifo_name + ',' + idx = out_fifo_idx + out_fifo_idx += 1 + else: + in_fifo_list += '\n ' + fifo_name + ',' + idx = in_fifo_idx + in_fifo_idx += 1 + + fifo_init_seq += '\n vtr.push_back(nirio_fifo_info_t(' + fifo_init_seq += dma_channel.find('Number').text + ', ' + fifo_init_seq += direction + 'S[' + str(idx) + '], ' + fifo_init_seq += direction + ', ' + fifo_init_seq += str.lower(base_addr) + ', ' + fifo_init_seq += dma_channel.find('NumberOfElements').text + ', ' + fifo_init_seq += 'SCALAR_' + dma_channel.find('DataType').find('SubType').text + ', ' + fifo_init_seq += dma_channel.find('DataType').find('WordLength').text + ', ' + fifo_init_seq += bitstream_version + fifo_init_seq += ')); //' + fifo_name + + +codegen_transform['fifo_init'] = fifo_init_seq +codegen_transform['out_fifo_list'] = out_fifo_list +codegen_transform['in_fifo_list'] = in_fifo_list + +# Merge bitstream into LVBITX +if (options.merge_bin is not None): + with open(os.path.abspath(options.merge_bin), 'rb') as bin_file: + bitstream = bin_file.read() + bitstream_md5 = hashlib.md5(bitstream).hexdigest() + bitstream_b64 = base64.b64encode(bitstream) + bitstream_b64_lb = '' + for i in range(0, len(bitstream_b64), 76): + bitstream_b64_lb += bitstream_b64[i:i+76] + '\n' + + root.find('Bitstream').text = bitstream_b64_lb + root.find('BitstreamMD5').text = bitstream_md5 + +codegen_transform['lvbitx_signature'] = str.upper(root.find('SignatureRegister').text) + +# Write BIN file +bitstream = base64.b64decode(root.find('Bitstream').text) +if (options.output_lvbitx_path is not None and hashlib.md5(bitstream).hexdigest() != root.find('BitstreamMD5').text): + print 'ERROR: The MD5 sum for the output LVBITX was incorrect. Make sure that the bitstream in the input LVBITX or BIN file is valid.' + sys.exit(1) +if (options.output_bin): + fpga_bin_file = open(os.path.join(options.output_lvbitx_path, class_name + '.bin'), 'w') + fpga_bin_file.write(bitstream) + fpga_bin_file.close() + +# Save LVBITX +if (options.output_lvbitx_path is not None): + tree.write(os.path.join(options.output_lvbitx_path, class_name + '_fpga.lvbitx'), encoding="utf-8", xml_declaration=True, default_namespace=None, method="xml") + +# Save HPP and CPP +with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'template_lvbitx.hpp'), 'r') as template_file: + template_string = template_file.read() +with open(os.path.join(autogen_src_path, class_name + '_lvbitx.hpp'), 'w') as source_file: + source_file.write(template_string.format(**codegen_transform)) + +with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'template_lvbitx.cpp'), 'r') as template_file: + template_string = template_file.read() +with open(os.path.join(autogen_src_path, class_name + '_lvbitx.cpp'), 'w') as source_file: + source_file.write(template_string.format(**codegen_transform)) + diff --git a/host/lib/transport/nirio/lvbitx/template_lvbitx.cpp b/host/lib/transport/nirio/lvbitx/template_lvbitx.cpp new file mode 100644 index 000000000..a1899c771 --- /dev/null +++ b/host/lib/transport/nirio/lvbitx/template_lvbitx.cpp @@ -0,0 +1,86 @@ +{autogen_msg} + +#include "{lvbitx_classname}_lvbitx.hpp" +#include <string> +#include <iostream> +#include <fstream> +#include <streambuf> +#include <boost/filesystem/path.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/regex.hpp> + +namespace uhd {{ namespace niusrprio {{ + +#define SEARCH_PATHS "{lvbitx_search_paths}" + +const char* {lvbitx_classname}_lvbitx::CONTROLS[] = {{{control_list} +}}; + +const char* {lvbitx_classname}_lvbitx::INDICATORS[] = {{{indicator_list} +}}; + +const char* {lvbitx_classname}_lvbitx::OUTPUT_FIFOS[] = {{{out_fifo_list} +}}; + +const char* {lvbitx_classname}_lvbitx::INPUT_FIFOS[] = {{{in_fifo_list} +}}; + +{lvbitx_classname}_lvbitx::{lvbitx_classname}_lvbitx(const std::string& option) +{{ + boost::filesystem::path fpga_path(_get_fpga_images_dir(SEARCH_PATHS)); + fpga_path /= "usrp_{lvbitx_classname}_fpga_" + option + ".lvbitx"; + _fpga_file_name = fpga_path.string(); + _bitstream_checksum = _get_bitstream_checksum(_fpga_file_name); +}} + +const char* {lvbitx_classname}_lvbitx::get_bitfile_path() {{ + return _fpga_file_name.c_str(); +}} + +const char* {lvbitx_classname}_lvbitx::get_signature() {{ + return "{lvbitx_signature}"; +}} + +const char* {lvbitx_classname}_lvbitx::get_bitstream_checksum() {{ + return _bitstream_checksum.c_str(); +}} + +size_t {lvbitx_classname}_lvbitx::get_input_fifo_count() {{ + return sizeof(INPUT_FIFOS)/sizeof(*INPUT_FIFOS); +}} + +const char** {lvbitx_classname}_lvbitx::get_input_fifo_names() {{ + return INPUT_FIFOS; +}} + +size_t {lvbitx_classname}_lvbitx::get_output_fifo_count() {{ + return sizeof(OUTPUT_FIFOS)/sizeof(*OUTPUT_FIFOS); +}} + +const char** {lvbitx_classname}_lvbitx::get_output_fifo_names() {{ + return OUTPUT_FIFOS; +}} + +size_t {lvbitx_classname}_lvbitx::get_control_count() {{ + return sizeof(CONTROLS)/sizeof(*CONTROLS); +}} + +const char** {lvbitx_classname}_lvbitx::get_control_names() {{ + return CONTROLS; +}} + +size_t {lvbitx_classname}_lvbitx::get_indicator_count() {{ + return sizeof(INDICATORS)/sizeof(*INDICATORS); +}} + +const char** {lvbitx_classname}_lvbitx::get_indicator_names() {{ + return INDICATORS; +}} + +void {lvbitx_classname}_lvbitx::init_register_info(nirio_register_info_vtr& vtr) {{ {register_init} +}} + +void {lvbitx_classname}_lvbitx::init_fifo_info(nirio_fifo_info_vtr& vtr) {{ {fifo_init} +}} + +}}}} diff --git a/host/lib/transport/nirio/lvbitx/template_lvbitx.hpp b/host/lib/transport/nirio/lvbitx/template_lvbitx.hpp new file mode 100644 index 000000000..d8872e15c --- /dev/null +++ b/host/lib/transport/nirio/lvbitx/template_lvbitx.hpp @@ -0,0 +1,48 @@ +{autogen_msg} + +#ifndef INCLUDED_{lvbitx_classname_u}_LVBITX_HPP +#define INCLUDED_{lvbitx_classname_u}_LVBITX_HPP + +#include <uhd/transport/nirio/nifpga_lvbitx.h> + +namespace uhd {{ namespace niusrprio {{ + +class {lvbitx_classname}_lvbitx : public nifpga_lvbitx {{ +public: + {lvbitx_classname}_lvbitx(const std::string& option); + + virtual ~{lvbitx_classname}_lvbitx() {{}}; + + virtual const char* get_bitfile_path(); + virtual const char* get_signature(); + virtual const char* get_bitstream_checksum(); + + virtual size_t get_input_fifo_count(); + virtual const char** get_input_fifo_names(); + + virtual size_t get_output_fifo_count(); + virtual const char** get_output_fifo_names(); + + virtual size_t get_control_count(); + virtual const char** get_control_names(); + + virtual size_t get_indicator_count(); + virtual const char** get_indicator_names(); + + virtual void init_register_info(nirio_register_info_vtr& vtr); + virtual void init_fifo_info(nirio_fifo_info_vtr& vtr); + + static const char* CONTROLS[]; + static const char* INDICATORS[]; + static const char* OUTPUT_FIFOS[]; + static const char* INPUT_FIFOS[]; + +private: + std::string _fpga_file_name; + std::string _bitstream_checksum; +}}; + +}}}} + +#endif /* INCLUDED_{lvbitx_classname_u}_LVBITX_HPP */ + diff --git a/host/lib/transport/nirio/lvbitx/x300.lvbitx_base b/host/lib/transport/nirio/lvbitx/x300.lvbitx_base new file mode 100755 index 000000000..c264e7157 --- /dev/null +++ b/host/lib/transport/nirio/lvbitx/x300.lvbitx_base @@ -0,0 +1,469 @@ +<?xml version="1.0" encoding="utf-8"?> +<Bitfile> + <BitfileVersion>4.0</BitfileVersion> + <Documentation> + <BuildSpecVersion/> + <BuildSpecDescription/> + </Documentation> + <SignatureRegister>97C6D9F4F4829001B83378F93CAB0C94</SignatureRegister> + <SignatureGuids>7BAD6AEB9741248079F13147B3F8AD94</SignatureGuids> + <SignatureNames>AE54C47F787D92DB46F7DC973338D786</SignatureNames> + <TimeStamp/> + <CompilationStatus/> + <BitstreamVersion>2</BitstreamVersion> + <VI> + <Name>USRP_X3x0_Top.vi</Name> + <RegisterList> + <Register> + <Name>ViSignature</Name> + <Hidden>true</Hidden> + <Indicator>true</Indicator> + <Datatype> + <Array> + <Name/> + <Size>4</Size> + <Type> + <U32> + <Name/> + </U32> + </Type> + </Array> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262132</Offset> + <SizeInBits>128</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>false</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>DiagramReset</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262140</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>ViControl</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262136</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>InterruptEnable</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262116</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>InterruptMask</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262124</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>InterruptStatus</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262128</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + </RegisterList> + <Icon> + <ImageType>0</ImageType> + <ImageDepth>8</ImageDepth> + <Image>////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA/////////////////////////wAAAAAAAAAAAP//AAD/+fn5+fn5+fn5+fn59/ks+SzgAAAAAAAAAAAA//8AAP/5///////////////3+Sz5LP8AAAAAAAAAAAD//wAA//n/6OTo////6OTo//f8K/ws/wAAAAAAAAAAAP//AAD/+f/k/+T////k/+T/9ywsLCzgAAAAAAAAAAAA//8AAP/56OT/5Oj/6OT/5Oj3K/wrLP8AAAAAAAAAAAD//wAA//nk6P/o5P/k6P/o5Pf8CPws/wAAAAAAAAAAAP//AAD/+eT////k/+T////k9/wI/Cz/AAAAAAAAAAAA//8AAP/5/////+jk6P/////3K/wrLP8AAAAAAAAAAAD//wAA//n///////////////csLCws/wAAAAAAAAAAAP//AAD/9/f39/f39/f39/f39ywsg4P/AAAAAAAAAAAA//8AAP8sLCwsLCwsLCwsLCwsLCyDBYODAAAAAAAAAAD//wAA/yz8LCwsLCz8LCwsLCMjI4MFBQWDgwAAAAAAAP//AAD//PD8LCws/CP8LCMjLCwsgwUF/wUFg4MAAAAA//8AAP8s7ywsLCwjLCwjLCwsLCyDBf///wUFBYMjIwD//wAA///w////I///I////////4MFBf8FBYODAAAAAP//AAAAAO8AAAAjAAAjAADw7+/wgwUFBYODAAAAAAAA//8AAAAAAPAAAAAjIwAA7wAAAACDBYODAAAAAAAAAAD//wAAAAAAAO/vAAAAAPAAAAAAAIODAAAAAAAAAAAAAP//AAAAAAAAAADw7/DvAAAAAAAAAAAAAAAAAP8AAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////////////////////////////////////w==</Image> + <Mask>//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8=</Mask> + <Colors>AP///wD//8wA//+ZAP//ZgD//zMA//8AAP/M/wD/zMwA/8yZAP/MZgD/zDMA/8wAAP+Z/wD/mcwA/5mZAP+ZZgD/mTMA/5kAAP9m/wD/ZswA/2aZAP9mZgD/ZjMA/2YAAP8z/wD/M8wA/zOZAP8zZgD/MzMA/zMAAP8A/wD/AMwA/wCZAP8AZgD/ADMA/wAAAMz//wDM/8wAzP+ZAMz/ZgDM/zMAzP8AAMzM/wDMzMwAzMyZAMzMZgDMzDMAzMwAAMyZ/wDMmcwAzJmZAMyZZgDMmTMAzJkAAMxm/wDMZswAzGaZAMxmZgDMZjMAzGYAAMwz/wDMM8wAzDOZAMwzZgDMMzMAzDMAAMwA/wDMAMwAzACZAMwAZgDMADMAzAAAAJn//wCZ/8wAmf+ZAJn/ZgCZ/zMAmf8AAJnM/wCZzMwAmcyZAJnMZgCZzDMAmcwAAJmZ/wCZmcwAmZmZAJmZZgCZmTMAmZkAAJlm/wCZZswAmWaZAJlmZgCZZjMAmWYAAJkz/wCZM8wAmTOZAJkzZgCZMzMAmTMAAJkA/wCZAMwAmQCZAJkAZgCZADMAmQAAAGb//wBm/8wAZv+ZAGb/ZgBm/zMAZv8AAGbM/wBmzMwAZsyZAGbMZgBmzDMAZswAAGaZ/wBmmcwAZpmZAGaZZgBmmTMAZpkAAGZm/wBmZswAZmaZAGZmZgBmZjMAZmYAAGYz/wBmM8wAZjOZAGYzZgBmMzMAZjMAAGYA/wBmAMwAZgCZAGYAZgBmADMAZgAAADP//wAz/8wAM/+ZADP/ZgAz/zMAM/8AADPM/wAzzMwAM8yZADPMZgAzzDMAM8wAADOZ/wAzmcwAM5mZADOZZgAzmTMAM5kAADNm/wAzZswAM2aZADNmZgAzZjMAM2YAADMz/wAzM8wAMzOZADMzZgAzMzMAMzMAADMA/wAzAMwAMwCZADMAZgAzADMAMwAAAAD//wAA/8wAAP+ZAAD/ZgAA/zMAAP8AAADM/wAAzMwAAMyZAADMZgAAzDMAAMwAAACZ/wAAmcwAAJmZAACZZgAAmTMAAJkAAABm/wAAZswAAGaZAABmZgAAZjMAAGYAAAAz/wAAM8wAADOZAAAzZgAAMzMAADMAAAAA/wAAAMwAAACZAAAAZgAAADMA7gAAAN0AAAC7AAAAqgAAAIgAAAB3AAAAVQAAAEQAAAAiAAAAEQAAAADuAAAA3QAAALsAAACqAAAAiAAAAHcAAABVAAAARAAAACIAAAARAAAAAO4AAADdAAAAuwAAAKoAAACIAAAAdwAAAFUAAABEAAAAIgAAABEA7u7uAN3d3QC7u7sAqqqqAIiIiAB3d3cAVVVVAERERAAiIiIAERERAAAAAA==</Colors> + <Rectangle> + <Left>0</Left> + <Top>0</Top> + <Right>32</Right> + <Bottom>32</Bottom> + </Rectangle> + </Icon> + </VI> + <Project> + <TargetClass>294XR; 295XR</TargetClass> + <AutoRunWhenDownloaded>false</AutoRunWhenDownloaded> + <CompilationResultsTree> + <CompilationResults> + <NiFpga> + <BaseAddressOnDevice>0</BaseAddressOnDevice> + <DmaChannelAllocationList> + <Channel name="RX FIFO 0"> + <BaseAddressTag>NiLvFpgaFIFO 0</BaseAddressTag> + <ControlSet>0</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>0</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 1"> + <BaseAddressTag>NiLvFpgaFIFO 1</BaseAddressTag> + <ControlSet>1</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>1</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 2"> + <BaseAddressTag>NiLvFpgaFIFO 2</BaseAddressTag> + <ControlSet>2</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>2</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 3"> + <BaseAddressTag>NiLvFpgaFIFO 3</BaseAddressTag> + <ControlSet>3</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>3</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 4"> + <BaseAddressTag>NiLvFpgaFIFO 4</BaseAddressTag> + <ControlSet>4</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>4</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 5"> + <BaseAddressTag>NiLvFpgaFIFO 5</BaseAddressTag> + <ControlSet>5</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>5</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 0"> + <BaseAddressTag>NiLvFpgaFIFO 6</BaseAddressTag> + <ControlSet>6</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>6</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 1"> + <BaseAddressTag>NiLvFpgaFIFO 7</BaseAddressTag> + <ControlSet>7</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>7</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 2"> + <BaseAddressTag>NiLvFpgaFIFO 8</BaseAddressTag> + <ControlSet>8</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>8</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 3"> + <BaseAddressTag>NiLvFpgaFIFO 9</BaseAddressTag> + <ControlSet>9</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>9</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 4"> + <BaseAddressTag>NiLvFpgaFIFO 10</BaseAddressTag> + <ControlSet>10</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>10</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 5"> + <BaseAddressTag>NiLvFpgaFIFO 11</BaseAddressTag> + <ControlSet>11</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>11</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + </DmaChannelAllocationList> + <RegisterBlockList> + <RegisterBlock name="NiLvFpgaFIFO 0"> + <Offset>0xFF80</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 1"> + <Offset>0xFF40</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 2"> + <Offset>0xFF00</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 3"> + <Offset>0xFEC0</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 4"> + <Offset>0xFE80</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 5"> + <Offset>0xFE40</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 6"> + <Offset>0xFE00</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 7"> + <Offset>0xFDC0</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 8"> + <Offset>0xFD80</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 9"> + <Offset>0xFD40</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 10"> + <Offset>0xFD00</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 11"> + <Offset>0xFCC0</Offset> + </RegisterBlock> + </RegisterBlockList> + <UsedBaseClockList> + <BaseClock name="ReliableClkIn"> + </BaseClock> + <BaseClock name="ChinchClk"> + </BaseClock> + <BaseClock name="40 MHz Onboard Clock"> + </BaseClock> + </UsedBaseClockList> + <version>1</version> + </NiFpga> + </CompilationResults> + </CompilationResultsTree> + <MultipleUserClocks>false</MultipleUserClocks> + <AllowImplicitEnableRemoval>false</AllowImplicitEnableRemoval> + </Project> + <ClientData/> + <BitstreamMD5>a72ba1716893a0bd02f88dac3ab28e1b</BitstreamMD5> + <Bitstream>a72ba1716893a0bd02f88dac3ab28e1b</Bitstream> +</Bitfile> diff --git a/host/lib/transport/nirio/lvbitx/x310.lvbitx_base b/host/lib/transport/nirio/lvbitx/x310.lvbitx_base new file mode 100755 index 000000000..c264e7157 --- /dev/null +++ b/host/lib/transport/nirio/lvbitx/x310.lvbitx_base @@ -0,0 +1,469 @@ +<?xml version="1.0" encoding="utf-8"?> +<Bitfile> + <BitfileVersion>4.0</BitfileVersion> + <Documentation> + <BuildSpecVersion/> + <BuildSpecDescription/> + </Documentation> + <SignatureRegister>97C6D9F4F4829001B83378F93CAB0C94</SignatureRegister> + <SignatureGuids>7BAD6AEB9741248079F13147B3F8AD94</SignatureGuids> + <SignatureNames>AE54C47F787D92DB46F7DC973338D786</SignatureNames> + <TimeStamp/> + <CompilationStatus/> + <BitstreamVersion>2</BitstreamVersion> + <VI> + <Name>USRP_X3x0_Top.vi</Name> + <RegisterList> + <Register> + <Name>ViSignature</Name> + <Hidden>true</Hidden> + <Indicator>true</Indicator> + <Datatype> + <Array> + <Name/> + <Size>4</Size> + <Type> + <U32> + <Name/> + </U32> + </Type> + </Array> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262132</Offset> + <SizeInBits>128</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>false</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>DiagramReset</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262140</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>ViControl</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262136</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>InterruptEnable</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262116</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>InterruptMask</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262124</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + <Register> + <Name>InterruptStatus</Name> + <Hidden>false</Hidden> + <Indicator>false</Indicator> + <Datatype> + <U32> + <Name/> + </U32> + </Datatype> + <FlattenedType/> + <Grouping/> + <Offset>262128</Offset> + <SizeInBits>32</SizeInBits> + <Class>0</Class> + <Internal>true</Internal> + <TypedefPath/> + <TypedefRelativePath/> + <ID>0</ID> + <Bidirectional>true</Bidirectional> + <Synchronous>false</Synchronous> + <MechanicalAction>Switch When Pressed</MechanicalAction> + <AccessMayTimeout>false</AccessMayTimeout> + <RegisterNode>false</RegisterNode> + <SubControlList/> + </Register> + </RegisterList> + <Icon> + <ImageType>0</ImageType> + <ImageDepth>8</ImageDepth> + <Image>////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA/////////////////////////wAAAAAAAAAAAP//AAD/+fn5+fn5+fn5+fn59/ks+SzgAAAAAAAAAAAA//8AAP/5///////////////3+Sz5LP8AAAAAAAAAAAD//wAA//n/6OTo////6OTo//f8K/ws/wAAAAAAAAAAAP//AAD/+f/k/+T////k/+T/9ywsLCzgAAAAAAAAAAAA//8AAP/56OT/5Oj/6OT/5Oj3K/wrLP8AAAAAAAAAAAD//wAA//nk6P/o5P/k6P/o5Pf8CPws/wAAAAAAAAAAAP//AAD/+eT////k/+T////k9/wI/Cz/AAAAAAAAAAAA//8AAP/5/////+jk6P/////3K/wrLP8AAAAAAAAAAAD//wAA//n///////////////csLCws/wAAAAAAAAAAAP//AAD/9/f39/f39/f39/f39ywsg4P/AAAAAAAAAAAA//8AAP8sLCwsLCwsLCwsLCwsLCyDBYODAAAAAAAAAAD//wAA/yz8LCwsLCz8LCwsLCMjI4MFBQWDgwAAAAAAAP//AAD//PD8LCws/CP8LCMjLCwsgwUF/wUFg4MAAAAA//8AAP8s7ywsLCwjLCwjLCwsLCyDBf///wUFBYMjIwD//wAA///w////I///I////////4MFBf8FBYODAAAAAP//AAAAAO8AAAAjAAAjAADw7+/wgwUFBYODAAAAAAAA//8AAAAAAPAAAAAjIwAA7wAAAACDBYODAAAAAAAAAAD//wAAAAAAAO/vAAAAAPAAAAAAAIODAAAAAAAAAAAAAP//AAAAAAAAAADw7/DvAAAAAAAAAAAAAAAAAP8AAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////////////////////////////////////w==</Image> + <Mask>//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8=</Mask> + <Colors>AP///wD//8wA//+ZAP//ZgD//zMA//8AAP/M/wD/zMwA/8yZAP/MZgD/zDMA/8wAAP+Z/wD/mcwA/5mZAP+ZZgD/mTMA/5kAAP9m/wD/ZswA/2aZAP9mZgD/ZjMA/2YAAP8z/wD/M8wA/zOZAP8zZgD/MzMA/zMAAP8A/wD/AMwA/wCZAP8AZgD/ADMA/wAAAMz//wDM/8wAzP+ZAMz/ZgDM/zMAzP8AAMzM/wDMzMwAzMyZAMzMZgDMzDMAzMwAAMyZ/wDMmcwAzJmZAMyZZgDMmTMAzJkAAMxm/wDMZswAzGaZAMxmZgDMZjMAzGYAAMwz/wDMM8wAzDOZAMwzZgDMMzMAzDMAAMwA/wDMAMwAzACZAMwAZgDMADMAzAAAAJn//wCZ/8wAmf+ZAJn/ZgCZ/zMAmf8AAJnM/wCZzMwAmcyZAJnMZgCZzDMAmcwAAJmZ/wCZmcwAmZmZAJmZZgCZmTMAmZkAAJlm/wCZZswAmWaZAJlmZgCZZjMAmWYAAJkz/wCZM8wAmTOZAJkzZgCZMzMAmTMAAJkA/wCZAMwAmQCZAJkAZgCZADMAmQAAAGb//wBm/8wAZv+ZAGb/ZgBm/zMAZv8AAGbM/wBmzMwAZsyZAGbMZgBmzDMAZswAAGaZ/wBmmcwAZpmZAGaZZgBmmTMAZpkAAGZm/wBmZswAZmaZAGZmZgBmZjMAZmYAAGYz/wBmM8wAZjOZAGYzZgBmMzMAZjMAAGYA/wBmAMwAZgCZAGYAZgBmADMAZgAAADP//wAz/8wAM/+ZADP/ZgAz/zMAM/8AADPM/wAzzMwAM8yZADPMZgAzzDMAM8wAADOZ/wAzmcwAM5mZADOZZgAzmTMAM5kAADNm/wAzZswAM2aZADNmZgAzZjMAM2YAADMz/wAzM8wAMzOZADMzZgAzMzMAMzMAADMA/wAzAMwAMwCZADMAZgAzADMAMwAAAAD//wAA/8wAAP+ZAAD/ZgAA/zMAAP8AAADM/wAAzMwAAMyZAADMZgAAzDMAAMwAAACZ/wAAmcwAAJmZAACZZgAAmTMAAJkAAABm/wAAZswAAGaZAABmZgAAZjMAAGYAAAAz/wAAM8wAADOZAAAzZgAAMzMAADMAAAAA/wAAAMwAAACZAAAAZgAAADMA7gAAAN0AAAC7AAAAqgAAAIgAAAB3AAAAVQAAAEQAAAAiAAAAEQAAAADuAAAA3QAAALsAAACqAAAAiAAAAHcAAABVAAAARAAAACIAAAARAAAAAO4AAADdAAAAuwAAAKoAAACIAAAAdwAAAFUAAABEAAAAIgAAABEA7u7uAN3d3QC7u7sAqqqqAIiIiAB3d3cAVVVVAERERAAiIiIAERERAAAAAA==</Colors> + <Rectangle> + <Left>0</Left> + <Top>0</Top> + <Right>32</Right> + <Bottom>32</Bottom> + </Rectangle> + </Icon> + </VI> + <Project> + <TargetClass>294XR; 295XR</TargetClass> + <AutoRunWhenDownloaded>false</AutoRunWhenDownloaded> + <CompilationResultsTree> + <CompilationResults> + <NiFpga> + <BaseAddressOnDevice>0</BaseAddressOnDevice> + <DmaChannelAllocationList> + <Channel name="RX FIFO 0"> + <BaseAddressTag>NiLvFpgaFIFO 0</BaseAddressTag> + <ControlSet>0</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>0</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 1"> + <BaseAddressTag>NiLvFpgaFIFO 1</BaseAddressTag> + <ControlSet>1</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>1</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 2"> + <BaseAddressTag>NiLvFpgaFIFO 2</BaseAddressTag> + <ControlSet>2</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>2</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 3"> + <BaseAddressTag>NiLvFpgaFIFO 3</BaseAddressTag> + <ControlSet>3</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>3</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 4"> + <BaseAddressTag>NiLvFpgaFIFO 4</BaseAddressTag> + <ControlSet>4</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>4</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="RX FIFO 5"> + <BaseAddressTag>NiLvFpgaFIFO 5</BaseAddressTag> + <ControlSet>5</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>TargetToHost</Direction> + <Implementation>niFpgaTargetToHost</Implementation> + <Number>5</Number> + <NumberOfElements>1023</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 0"> + <BaseAddressTag>NiLvFpgaFIFO 6</BaseAddressTag> + <ControlSet>6</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>6</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 1"> + <BaseAddressTag>NiLvFpgaFIFO 7</BaseAddressTag> + <ControlSet>7</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>7</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 2"> + <BaseAddressTag>NiLvFpgaFIFO 8</BaseAddressTag> + <ControlSet>8</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>8</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 3"> + <BaseAddressTag>NiLvFpgaFIFO 9</BaseAddressTag> + <ControlSet>9</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>9</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 4"> + <BaseAddressTag>NiLvFpgaFIFO 10</BaseAddressTag> + <ControlSet>10</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>10</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + <Channel name="TX FIFO 5"> + <BaseAddressTag>NiLvFpgaFIFO 11</BaseAddressTag> + <ControlSet>11</ControlSet> + <DataType> + <Delta>1.000000000000000000000000000000000000000000000000000000</Delta> + <IntegerWordLength>64</IntegerWordLength> + <Maximum>18446744073709551600.00000000000000000000000000000000000</Maximum> + <Minimum>0.000000000000000000000000000000000000000000000000000000</Minimum> + <Signed>false</Signed> + <SubType>U64</SubType> + <WordLength>64</WordLength> + </DataType> + <Direction>HostToTarget</Direction> + <Implementation>niFpgaHostToTarget</Implementation> + <Number>11</Number> + <NumberOfElements>1029</NumberOfElements> + <UserVisible>true</UserVisible> + </Channel> + </DmaChannelAllocationList> + <RegisterBlockList> + <RegisterBlock name="NiLvFpgaFIFO 0"> + <Offset>0xFF80</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 1"> + <Offset>0xFF40</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 2"> + <Offset>0xFF00</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 3"> + <Offset>0xFEC0</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 4"> + <Offset>0xFE80</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 5"> + <Offset>0xFE40</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 6"> + <Offset>0xFE00</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 7"> + <Offset>0xFDC0</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 8"> + <Offset>0xFD80</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 9"> + <Offset>0xFD40</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 10"> + <Offset>0xFD00</Offset> + </RegisterBlock> + <RegisterBlock name="NiLvFpgaFIFO 11"> + <Offset>0xFCC0</Offset> + </RegisterBlock> + </RegisterBlockList> + <UsedBaseClockList> + <BaseClock name="ReliableClkIn"> + </BaseClock> + <BaseClock name="ChinchClk"> + </BaseClock> + <BaseClock name="40 MHz Onboard Clock"> + </BaseClock> + </UsedBaseClockList> + <version>1</version> + </NiFpga> + </CompilationResults> + </CompilationResultsTree> + <MultipleUserClocks>false</MultipleUserClocks> + <AllowImplicitEnableRemoval>false</AllowImplicitEnableRemoval> + </Project> + <ClientData/> + <BitstreamMD5>a72ba1716893a0bd02f88dac3ab28e1b</BitstreamMD5> + <Bitstream>a72ba1716893a0bd02f88dac3ab28e1b</Bitstream> +</Bitfile> diff --git a/host/lib/transport/nirio/nifpga_lvbitx.cpp b/host/lib/transport/nirio/nifpga_lvbitx.cpp new file mode 100644 index 000000000..289a44d4a --- /dev/null +++ b/host/lib/transport/nirio/nifpga_lvbitx.cpp @@ -0,0 +1,138 @@ +// +// Copyright 2013-2014 Ettus Research LLC +// +// 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/>. +// + +#include <uhd/transport/nirio/nifpga_lvbitx.h> +#include <string> +#include <iostream> +#include <fstream> +#include <streambuf> +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <boost/filesystem.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/regex.hpp> + +namespace uhd { namespace niusrprio { + +std::string nifpga_lvbitx::_get_bitstream_checksum(const std::string& file_path) +{ + std::string checksum; + std::ifstream lvbitx_stream(file_path.c_str()); + if (lvbitx_stream.is_open()) { + std::string lvbitx_contents; + lvbitx_stream.seekg(0, std::ios::end); + lvbitx_contents.reserve(static_cast<size_t>(lvbitx_stream.tellg())); + lvbitx_stream.seekg(0, std::ios::beg); + lvbitx_contents.assign((std::istreambuf_iterator<char>(lvbitx_stream)), std::istreambuf_iterator<char>()); + try { + boost::smatch md5_match; + if (boost::regex_search(lvbitx_contents, md5_match, boost::regex("<BitstreamMD5>([a-zA-Z0-9]{32})<\\/BitstreamMD5>", boost::regex::icase))) { + checksum = std::string(md5_match[1].first, md5_match[1].second); + } + } catch (boost::exception&) { + checksum = ""; + } + } + boost::to_upper(checksum); + return checksum; +} + +#ifdef UHD_PLATFORM_WIN32 +#include <windows.h> + +std::string _get_path_from_registry(const std::string& registry_key_path) +{ + boost::smatch reg_key_match; + //If a substring in the search path is enclosed in [] (square brackets) then it is interpreted as a registry path + if (not boost::regex_search(registry_key_path, reg_key_match, boost::regex("\\[(.+)\\](.*)", boost::regex::icase))) + return std::string(); + std::string reg_key_path = std::string(reg_key_match[1].first, reg_key_match[1].second); + std::string path_suffix = std::string(reg_key_match[2].first, reg_key_match[2].second); + + //Split the registry path into parent, key-path and value. + boost::smatch reg_parent_match; + if (not boost::regex_search(reg_key_path, reg_parent_match, boost::regex("^(.+?)\\\\(.+)\\\\(.+)$", boost::regex::icase))) + return std::string(); + std::string reg_parent = std::string(reg_parent_match[1].first, reg_parent_match[1].second); + std::string reg_path = std::string(reg_parent_match[2].first, reg_parent_match[2].second); + std::string reg_val_name = std::string(reg_parent_match[3].first, reg_parent_match[3].second); + + HKEY hkey_parent = HKEY_LOCAL_MACHINE; + if (reg_parent == "HKEY_LOCAL_MACHINE") hkey_parent = HKEY_LOCAL_MACHINE; + else if (reg_parent == "HKEY_CURRENT_USER") hkey_parent = HKEY_CURRENT_USER; + else if (reg_parent == "HKEY_CLASSES_ROOT") hkey_parent = HKEY_CLASSES_ROOT; + else if (reg_parent == "HKEY_CURRENT_CONFIG") hkey_parent = HKEY_CURRENT_CONFIG; + else if (reg_parent == "HKEY_USERS") hkey_parent = HKEY_CURRENT_USER; + + TCHAR value_buff[1024]; + DWORD value_buff_size = 1024*sizeof(TCHAR); + + //Get a handle to the key location + HKEY hkey_location; + if (RegOpenKeyExA(hkey_parent, reg_path.c_str(), NULL, KEY_QUERY_VALUE, &hkey_location) != ERROR_SUCCESS) + return std::string(); + + //Query key value + DWORD dw_type = REG_SZ; + if(RegQueryValueExA(hkey_location, reg_val_name.c_str(), NULL, &dw_type, (LPBYTE)value_buff, &value_buff_size) == ERROR_SUCCESS) { + RegCloseKey(hkey_location); + if (value_buff_size >= 1024*sizeof(TCHAR)) { + return std::string(); + } else { + std::string return_value(value_buff, value_buff_size-1); //value_buff_size includes the null terminator + return_value += path_suffix; + return return_value; + } + } else { + return std::string(); + } +} + +#endif /*UHD_PLATFORM_WIN32*/ + +std::string nifpga_lvbitx::_get_fpga_images_dir(const std::string search_paths) +{ + std::vector<std::string> search_path_vtr; + boost::split(search_path_vtr, search_paths, boost::is_any_of(",")); + + std::string lvbitx_dir; + //Traverse through the list of search paths. Priority: lexical + BOOST_FOREACH(std::string& search_path, search_path_vtr) { + boost::algorithm::trim(search_path); + if (search_path.empty()) continue; + +#ifdef UHD_PLATFORM_WIN32 + lvbitx_dir = _get_path_from_registry(search_path); + if (lvbitx_dir.empty()) { + //Could not read from the registry due to missing key, invalid values, etc + //Just use the search path. The is_directory check will fail if this is a + //registry path and we will move on to the next item in the list. + lvbitx_dir = search_path; + } +#else + lvbitx_dir = search_path; +#endif + + //If the current directory exists then stop traversing the search path list. + if (boost::filesystem::is_directory(lvbitx_dir)) break; + } + + return lvbitx_dir; +} + + +}} diff --git a/host/lib/transport/nirio/nirio_driver_iface_linux.cpp b/host/lib/transport/nirio/nirio_driver_iface_linux.cpp new file mode 100644 index 000000000..b1f4bb49f --- /dev/null +++ b/host/lib/transport/nirio/nirio_driver_iface_linux.cpp @@ -0,0 +1,111 @@ +// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// + +#include <uhd/transport/nirio/nirio_driver_iface.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +namespace nirio_driver_iface { + +nirio_status rio_open( + const std::string& device_path, + rio_dev_handle_t& device_handle) +{ + device_handle = ::open(device_path.c_str(), O_RDWR | O_CLOEXEC); + return (device_handle < 0) ? NiRio_Status_InvalidParameter : NiRio_Status_Success; +} + +void rio_close(rio_dev_handle_t& device_handle) +{ + ::close(device_handle); + device_handle = -1; +} + +bool rio_isopen(rio_dev_handle_t device_handle) +{ + return (device_handle >= 0); +} + +nirio_status rio_ioctl( + rio_dev_handle_t device_handle, + uint32_t ioctl_code, + const void *write_buf, + size_t write_buf_len, + void *read_buf, + size_t read_buf_len) +{ + nirio_ioctl_block_t ioctl_block = {0,0,0,0,0,0}; + + // two-casts necessary to prevent pointer sign-extension + ioctl_block.inBuf = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(write_buf)); + ioctl_block.inBufLength = write_buf_len; + ioctl_block.outBuf = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(read_buf)); + ioctl_block.outBufLength = read_buf_len; + + int status = ::ioctl(device_handle, ioctl_code, &ioctl_block); + if (status == -1) { + switch (errno) { + case EINVAL: return NiRio_Status_InvalidParameter; + case EFAULT: return NiRio_Status_MemoryFull; + default: return NiRio_Status_SoftwareFault; + } + } else { + return NiRio_Status_Success; + } +} + +nirio_status rio_mmap( + rio_dev_handle_t device_handle, + uint16_t memory_type, + size_t size, + bool writable, + rio_mmap_t &map) +{ + int access_mode = PROT_READ; //Write-only mode not supported + if (writable) access_mode |= PROT_WRITE; + map.addr = ::mmap(NULL, size, access_mode, MAP_SHARED, device_handle, (off_t) memory_type * sysconf(_SC_PAGESIZE)); + map.size = size; + + if (map.addr == MAP_FAILED) { + map.addr = NULL; + map.size = 0; + switch (errno) { + case EINVAL: return NiRio_Status_InvalidParameter; + case EFAULT: return NiRio_Status_MemoryFull; + default: return NiRio_Status_SoftwareFault; + } + } + return NiRio_Status_Success; +} + +nirio_status rio_munmap(rio_mmap_t &map) +{ + nirio_status status = 0; + if (map.addr != NULL) { + status = ::munmap(map.addr, map.size); + + map.addr = NULL; + map.size = 0; + } + return status; +} + +} diff --git a/host/lib/transport/nirio/nirio_driver_iface_macos.cpp b/host/lib/transport/nirio/nirio_driver_iface_macos.cpp new file mode 100644 index 000000000..1a1142525 --- /dev/null +++ b/host/lib/transport/nirio/nirio_driver_iface_macos.cpp @@ -0,0 +1,63 @@ +// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// +#include <uhd/transport/nirio/nirio_driver_iface.h> + +namespace nirio_driver_iface { + +nirio_status rio_open( + const std::string& device_path, + rio_dev_handle_t& device_handle) +{ + return NiRio_Status_FeatureNotSupported; +} + +void rio_close(rio_dev_handle_t& device_handle) +{ +} + +bool rio_isopen(rio_dev_handle_t device_handle) +{ + return false; +} + +nirio_status rio_ioctl( + rio_dev_handle_t device_handle, + uint32_t ioctl_code, + const void *write_buf, + size_t write_buf_len, + void *read_buf, + size_t read_buf_len) +{ + return NiRio_Status_FeatureNotSupported; +} + +nirio_status rio_mmap( + rio_dev_handle_t device_handle, + uint16_t memory_type, + size_t size, + bool writable, + rio_mmap_t &map) +{ + return NiRio_Status_FeatureNotSupported; +} + +nirio_status rio_munmap(rio_mmap_t &map) +{ + return NiRio_Status_FeatureNotSupported; +} + +} diff --git a/host/lib/transport/nirio/nirio_driver_iface_win.cpp b/host/lib/transport/nirio/nirio_driver_iface_win.cpp new file mode 100644 index 000000000..b47c6ce85 --- /dev/null +++ b/host/lib/transport/nirio/nirio_driver_iface_win.cpp @@ -0,0 +1,148 @@ +// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// + +#include <uhd/transport/nirio/nirio_driver_iface.h> +#include <process.h> + +#define NIRIO_IOCTL_MAP_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0xF00, METHOD_BUFFERED, (FILE_READ_ACCESS | FILE_WRITE_ACCESS)) +#define NIRIO_IOCTL_UNMAP_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0xF01, METHOD_BUFFERED, (FILE_READ_ACCESS | FILE_WRITE_ACCESS)) + +namespace nirio_driver_iface { + +nirio_status rio_open( + const std::string& device_path, + rio_dev_handle_t& device_handle) +{ + device_handle = CreateFileA(device_path.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, /* default security */ + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL /* template file */); + + return (device_handle == INVALID_HANDLE_VALUE) ? NiRio_Status_InvalidParameter : NiRio_Status_Success; +} + +void rio_close(rio_dev_handle_t& device_handle) +{ + ::CloseHandle(device_handle); + device_handle = INVALID_HANDLE_VALUE; +} + +bool rio_isopen(rio_dev_handle_t device_handle) +{ + return (device_handle != INVALID_HANDLE_VALUE); +} + +nirio_status rio_ioctl( + rio_dev_handle_t device_handle, + uint32_t ioctl_code, + const void *write_buf, + size_t write_buf_len, + void *read_buf, + size_t read_buf_len) +{ + if (!rio_isopen(device_handle)) return NiRio_Status_ResourceNotInitialized; + + /* Note, if the file handle was opened with the OVERLAPPED flag, you must + * supply an OVERLAPPED structure to ReadFile, WriteFile, and + * DeviceIoControl, even when doing synchronous IO. */ + OVERLAPPED zeroedOverlapped = {0}; + DWORD outLen = 0; + int_fast32_t lastError = 0; + + if (!(DeviceIoControl(device_handle, ioctl_code, + const_cast<void*>(write_buf), static_cast<DWORD>(write_buf_len), + read_buf, static_cast<DWORD>(read_buf_len), + &outLen, &zeroedOverlapped ))) + { + lastError = GetLastError(); + return NiRio_Status_SoftwareFault; + } + + return NiRio_Status_Success; +} + +unsigned int __stdcall memory_map_thread_routine(void *context) +{ + rio_mmap_threadargs_t *args = (rio_mmap_threadargs_t*)context; + args->status = rio_ioctl(args->device_handle, NIRIO_IOCTL_MAP_MEMORY, &(args->params), sizeof(args->params), NULL, 0); + if (nirio_status_fatal(args->status)) + { + SetEvent(reinterpret_cast<HANDLE>(args->params.map_ready_event_handle)); + } + return 0; +} + +nirio_status rio_mmap( + rio_dev_handle_t device_handle, + uint16_t memory_type, + size_t size, + bool writable, + rio_mmap_t &map) +{ + if (!rio_isopen(device_handle)) return NiRio_Status_ResourceNotInitialized; + + access_mode_t access_mode = writable ? ACCESS_MODE_WRITE : ACCESS_MODE_READ; + + uint64_t mapped_addr = 0; + map.map_thread_args.device_handle = device_handle; + map.map_thread_args.status = NiRio_Status_Success; + map.map_thread_args.params.memoryType = memory_type; + map.map_thread_args.params.size = (uint32_t)size; + map.map_thread_args.params.mapped_va_ptr = reinterpret_cast<uintptr_t>(&mapped_addr); + map.map_thread_args.params.access_mode = (uint8_t)access_mode; + HANDLE map_ready_event_handle = CreateEventA(NULL, TRUE, FALSE, NULL); + if (map_ready_event_handle == NULL) { + map.addr = NULL; + return NiRio_Status_SoftwareFault; + } + map.map_thread_args.params.map_ready_event_handle = reinterpret_cast<uint64_t>(map_ready_event_handle); + map.map_thread_handle = (HANDLE) _beginthreadex(NULL, 0, memory_map_thread_routine, &(map.map_thread_args), 0, NULL); + + nirio_status status = NiRio_Status_Success; + if (map.map_thread_handle == NULL) { + map.addr = NULL; + return NiRio_Status_SoftwareFault; + } else { + WaitForSingleObject(map_ready_event_handle, INFINITE); + map.addr = reinterpret_cast<void*>(mapped_addr); + if (map.addr == NULL) { + WaitForSingleObject(map.map_thread_handle, INFINITE); + CloseHandle(map.map_thread_handle); + nirio_status_chain(map.map_thread_args.status, status); + } + } + CloseHandle(map_ready_event_handle); + return status; +} + +nirio_status rio_munmap(rio_mmap_t &map) +{ + if (!rio_isopen(map.map_thread_args.device_handle)) return NiRio_Status_ResourceNotInitialized; + + nirio_status status = NiRio_Status_Success; + if (map.addr != NULL) { + uint64_t mapped_addr = reinterpret_cast<uintptr_t>(map.addr); + status = rio_ioctl(map.map_thread_args.device_handle, NIRIO_IOCTL_UNMAP_MEMORY, &mapped_addr, sizeof(mapped_addr), NULL, 0); + if (nirio_status_not_fatal(status)) { + WaitForSingleObject(map.map_thread_handle, INFINITE); + } + CloseHandle(map.map_thread_handle); + map.addr = NULL; + } + return status; +} + +} diff --git a/host/lib/transport/nirio/nirio_resource_manager.cpp b/host/lib/transport/nirio/nirio_resource_manager.cpp new file mode 100644 index 000000000..85e789087 --- /dev/null +++ b/host/lib/transport/nirio/nirio_resource_manager.cpp @@ -0,0 +1,120 @@ +// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// + + +#include <uhd/transport/nirio/nirio_resource_manager.h> + +#ifdef __clang__ + #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" +#elif defined(__GNUC__) + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +namespace uhd { namespace niusrprio +{ + +nirio_resource_manager::nirio_resource_manager( + niriok_proxy& proxy) : _kernel_proxy(proxy), _fifo_info_map(), _reg_info_map() +{ +} + +nirio_resource_manager::~nirio_resource_manager() +{ + finalize(); +} + +nirio_status nirio_resource_manager::initialize( + const nirio_register_info_vtr& reg_info_vtr, + const nirio_fifo_info_vtr& fifo_info_vtr) +{ + nirio_status status = 0; + for (nirio_fifo_info_vtr::const_iterator it = fifo_info_vtr.begin(); it != fifo_info_vtr.end(); it++) { + const nirio_fifo_info_t& fifo_info = *it; + status = _add_fifo_resource(fifo_info); + if (nirio_status_fatal(status)) return status; + + _fifo_info_map.insert(fifo_info_map_t::value_type(fifo_info.name, fifo_info)); + } + for (nirio_register_info_vtr::const_iterator it = reg_info_vtr.begin(); it != reg_info_vtr.end(); it++) { + const nirio_register_info_t& reg_info = *it; + + _reg_info_map.insert(register_info_map_t::value_type(reg_info.name, reg_info)); + } + return _set_driver_config(); +} + +void nirio_resource_manager::finalize() +{ + _fifo_info_map.clear(); +} + +nirio_status nirio_resource_manager::get_register_offset( + const char* register_name, + uint32_t& offset) +{ + register_info_map_t::const_iterator it = _reg_info_map.find(fifo_info_map_t::key_type(register_name)); + if (it == _reg_info_map.end()) return NiRio_Status_InvalidParameter; + + offset = (*it).second.offset; + + return NiRio_Status_Success; +} + + +nirio_status nirio_resource_manager::_add_fifo_resource( + const nirio_fifo_info_t& fifo_info) +{ + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::ADD_RESOURCE; + in.subfunction = (fifo_info.direction == OUTPUT_FIFO) ? + nirio_driver_iface::NIRIO_RESOURCE::OUTPUT_FIFO : + nirio_driver_iface::NIRIO_RESOURCE::INPUT_FIFO; + + in.params.add.fifoWithDataType.channel = fifo_info.channel; + in.params.add.fifoWithDataType.baseAddress = fifo_info.base_addr; + in.params.add.fifoWithDataType.depthInSamples = fifo_info.depth; + in.params.add.fifoWithDataType.scalarType = fifo_info.scalar_type; + in.params.add.fifoWithDataType.bitWidth = fifo_info.width; + in.params.add.fifoWithDataType.version = fifo_info.version; + + return _kernel_proxy.sync_operation(&in, sizeof(in), &out, sizeof(out)); +} + +nirio_status nirio_resource_manager::_set_driver_config() +{ + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + in.function = nirio_driver_iface::NIRIO_FUNC::SET_DRIVER_CONFIG; + in.subfunction = 0; + + return _kernel_proxy.sync_operation(&in, sizeof(in), &out, sizeof(out)); +} + +nirio_fifo_info_t* nirio_resource_manager::_lookup_fifo_info(const char* fifo_name) { + fifo_info_map_t::iterator it = _fifo_info_map.find(fifo_info_map_t::key_type(fifo_name)); + if (it == _fifo_info_map.end()) return NULL; + + return &((*it).second); +} + +}} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif diff --git a/host/lib/transport/nirio/niriok_proxy.cpp b/host/lib/transport/nirio/niriok_proxy.cpp new file mode 100644 index 000000000..031623c9a --- /dev/null +++ b/host/lib/transport/nirio/niriok_proxy.cpp @@ -0,0 +1,300 @@ +// +// Copyright 2013-2014 Ettus Research LLC +// +// 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/>. +// + + +#include <uhd/transport/nirio/niriok_proxy.h> +#include <cstring> + +#define NI_VENDOR_NUM 0x1093 + +#define VERSION_BUILD_SHIFT 0 +#define VERSION_PHASE_SHIFT 14 +#define VERSION_MAINT_SHIFT 16 +#define VERSION_UPGRD_SHIFT 20 +#define VERSION_MAJOR_SHIFT 24 +#define VERSION_BUILD_MASK 0x00003FFF +#define VERSION_PHASE_MASK 0x0000C000 +#define VERSION_MAINT_MASK 0x000F0000 +#define VERSION_UPGRD_MASK 0x00F00000 +#define VERSION_MAJOR_MASK 0xFF000000 + +#define GET_FIFO_MEMORY_TYPE(fifo_inst) (static_cast<uint16_t>(0x0100 | static_cast<uint16_t>(fifo_inst))) + +#ifdef __clang__ + #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" +#elif defined(__GNUC__) + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +namespace uhd { namespace niusrprio +{ + //------------------------------------------------------- + // niriok_proxy + //------------------------------------------------------- + niriok_proxy::niriok_proxy(): _device_handle(nirio_driver_iface::INVALID_RIO_HANDLE) + { + } + + niriok_proxy::~niriok_proxy() + { + close(); + } + + nirio_status niriok_proxy::open(const std::string& interface_path) + { + if (interface_path.empty()) return NiRio_Status_ResourceNotFound; + + //close if already open. + close(); + + nirio_status status = NiRio_Status_Success; + nirio_status_chain(nirio_driver_iface::rio_open( + interface_path, _device_handle), status); + if (nirio_status_not_fatal(status)) { + nirio_status_chain(nirio_driver_iface::rio_ioctl(_device_handle, + nirio_driver_iface::NIRIO_IOCTL_POST_OPEN, + NULL, 0, NULL, 0), status); + nirio_driver_iface::nirio_ioctl_packet_t out(&_interface_num, sizeof(_interface_num), 0); + nirio_status_chain(nirio_driver_iface::rio_ioctl(_device_handle, + nirio_driver_iface::NIRIO_IOCTL_GET_IFACE_NUM, + NULL, 0, + &out, sizeof(out)), status); + + if (nirio_status_fatal(status)) close(); + } + return status; + } + + void niriok_proxy::close(void) + { + if(nirio_driver_iface::rio_isopen(_device_handle)) + { + nirio_driver_iface::rio_ioctl( + _device_handle, nirio_driver_iface::NIRIO_IOCTL_PRE_CLOSE, NULL, 0, NULL, 0); + nirio_driver_iface::rio_close(_device_handle); + } + } + + nirio_status niriok_proxy::reset() + { + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::RESET; + + return sync_operation(&in, sizeof(in), &out, sizeof(out)); + } + + nirio_status niriok_proxy::get_cached_session( + uint32_t& session) + { + nirio_driver_iface::nirio_ioctl_packet_t out(&session, sizeof(session), 0); + return nirio_driver_iface::rio_ioctl(_device_handle, + nirio_driver_iface::NIRIO_IOCTL_GET_SESSION, + NULL, 0, + &out, sizeof(out)); + } + + nirio_status niriok_proxy::get_version( + nirio_version_t type, + uint32_t& major, + uint32_t& upgrade, + uint32_t& maintenance, + char& phase, + uint32_t& build) + { + nirio_device_attr_32_t version_attr = (type==CURRENT)?CURRENT_VERSION:OLDEST_COMPATIBLE_VERSION; + uint32_t raw_version = 0; + nirio_status status = get_attribute(version_attr, raw_version); + + major = (raw_version & VERSION_MAJOR_MASK) >> VERSION_MAJOR_SHIFT; + upgrade = (raw_version & VERSION_UPGRD_MASK) >> VERSION_UPGRD_SHIFT; + maintenance = (raw_version & VERSION_MAINT_MASK) >> VERSION_MAINT_SHIFT; + build = (raw_version & VERSION_BUILD_MASK) >> VERSION_BUILD_SHIFT; + + uint32_t phase_num = (raw_version & VERSION_PHASE_MASK) >> VERSION_PHASE_SHIFT; + switch (phase_num) { + case 0: phase = 'd'; break; + case 1: phase = 'a'; break; + case 2: phase = 'b'; break; + case 3: phase = 'f'; break; + } + + return status; + } + + nirio_status niriok_proxy::sync_operation( + const void *writeBuffer, + size_t writeBufferLength, + void *readBuffer, + size_t readBufferLength) + { + nirio_driver_iface::nirio_ioctl_packet_t out(readBuffer, readBufferLength, 0); + nirio_status ioctl_status = nirio_driver_iface::rio_ioctl(_device_handle, + nirio_driver_iface::NIRIO_IOCTL_SYNCOP, + writeBuffer, writeBufferLength, + &out, sizeof(out)); + if (nirio_status_fatal(ioctl_status)) return ioctl_status; + + return out.statusCode; + } + + nirio_status niriok_proxy::get_attribute( + const nirio_device_attr_32_t attribute, + uint32_t& attrValue) + { + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::GET32; + in.params.attribute32.attribute = attribute; + + nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out)); + + attrValue = out.params.attribute32.value; + return status; + } + + nirio_status niriok_proxy::get_attribute( + const nirio_device_attr_str_t attribute, + char *buf, + const uint32_t bufLen, + uint32_t& stringLen) + { + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + nirio_driver_iface::init_syncop_out_params(out, buf, bufLen); + + in.function = nirio_driver_iface::NIRIO_FUNC::GET_STRING; + in.params.attributeStr.attribute = attribute; + + nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out)); + + stringLen = out.params.stringLength; + return status; + } + + nirio_status niriok_proxy::set_attribute( + const nirio_device_attr_32_t attribute, + const uint32_t value) + { + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::SET32; + in.params.attribute32.attribute = attribute; + in.params.attribute32.value = value; + + return sync_operation(&in, sizeof(in), &out, sizeof(out)); + } + + nirio_status niriok_proxy::set_attribute( + const nirio_device_attr_str_t attribute, + const char* const buffer) + { + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::init_syncop_in_params(in, buffer, strlen(buffer) + 1); + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::SET_STRING; + in.params.attributeStr.attribute = attribute; + + return sync_operation(&in, sizeof(in), &out, sizeof(out)); + } + + nirio_status niriok_proxy::peek(uint32_t offset, uint32_t& value) + { + if (offset % 4 != 0) return NiRio_Status_MisalignedAccess; + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::IO; + in.subfunction = nirio_driver_iface::NIRIO_IO::PEEK32; + in.params.io.offset = offset; + + nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out)); + value = out.params.io.value.value32; + return status; + } + + nirio_status niriok_proxy::peek(uint32_t offset, uint64_t& value) + { + if (offset % 8 != 0) return NiRio_Status_MisalignedAccess; + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::IO; + in.subfunction = nirio_driver_iface::NIRIO_IO::PEEK64; + in.params.io.offset = offset; + + nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out)); + value = out.params.io.value.value64; + return status; + } + + nirio_status niriok_proxy::poke(uint32_t offset, const uint32_t& value) + { + if (offset % 4 != 0) return NiRio_Status_MisalignedAccess; + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::IO; + in.subfunction = nirio_driver_iface::NIRIO_IO::POKE32; + in.params.io.offset = offset; + in.params.io.value.value32 = value; + + return sync_operation(&in, sizeof(in), &out, sizeof(out)); + } + + nirio_status niriok_proxy::poke(uint32_t offset, const uint64_t& value) + { + if (offset % 8 != 0) return NiRio_Status_MisalignedAccess; + + nirio_driver_iface::nirio_syncop_in_params_t in = {}; + nirio_driver_iface::nirio_syncop_out_params_t out = {}; + + in.function = nirio_driver_iface::NIRIO_FUNC::IO; + in.subfunction = nirio_driver_iface::NIRIO_IO::POKE64; + in.params.io.offset = offset; + in.params.io.value.value64 = value; + + return sync_operation(&in, sizeof(in), &out, sizeof(out)); + } + + nirio_status niriok_proxy::map_fifo_memory( + uint32_t fifo_instance, + size_t size, + nirio_driver_iface::rio_mmap_t& map) + { + return nirio_driver_iface::rio_mmap(_device_handle, + GET_FIFO_MEMORY_TYPE(fifo_instance), + size, true, map); + } + + nirio_status niriok_proxy::unmap_fifo_memory( + nirio_driver_iface::rio_mmap_t& map) + { + return nirio_driver_iface::rio_munmap(map); + } +}} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp new file mode 100644 index 000000000..a07bc4fdf --- /dev/null +++ b/host/lib/transport/nirio/niusrprio_session.cpp @@ -0,0 +1,199 @@ +// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// + + +#include <uhd/transport/nirio/niusrprio_session.h> +#include <uhd/transport/nirio/nirio_fifo.h> +#include <uhd/transport/nirio/status.h> +#include <boost/format.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/lexical_cast.hpp> +#include <stdio.h> +#include <fstream> +//@TODO: Move the register defs required by the class to a common location +#include "../../usrp/x300/x300_regs.hpp" + +namespace uhd { namespace niusrprio { + +niusrprio_session::niusrprio_session(const std::string& resource_name, const std::string& rpc_port_name) : + _resource_name(resource_name), + _session_open(false), + _resource_manager(_riok_proxy), + _rpc_client("localhost", rpc_port_name) +{ +} + +niusrprio_session::~niusrprio_session() +{ + close(); +} + +nirio_status niusrprio_session::enumerate(const std::string& rpc_port_name, device_info_vtr& device_info_vtr) +{ + usrprio_rpc::usrprio_rpc_client temp_rpc_client("localhost", rpc_port_name); + nirio_status status = temp_rpc_client.get_ctor_status(); + nirio_status_chain(temp_rpc_client.niusrprio_enumerate(device_info_vtr), status); + return status; +} + +nirio_status niusrprio_session::open( + nifpga_lvbitx::sptr lvbitx, + bool force_download) +{ + boost::unique_lock<boost::recursive_mutex> lock(_session_mutex); + + _lvbitx = lvbitx; + + nirio_status status = NiRio_Status_Success; + std::string bitfile_path(_lvbitx->get_bitfile_path()); + std::string signature(_lvbitx->get_signature()); + + //Make sure that the RPC client connected to the server properly + nirio_status_chain(_rpc_client.get_ctor_status(), status); + //Get a handle to the kernel driver + nirio_status_chain(_rpc_client.niusrprio_get_interface_path(_resource_name, _interface_path), status); + nirio_status_chain(_riok_proxy.open(_interface_path), status); + + if (nirio_status_not_fatal(status)) { + //Bitfile build for a particular LVFPGA interface will have the same signature + //because the API of the bitfile does not change. Two files with the same signature + //can however have different bitstreams because of non-LVFPGA code differences. + //That is why we need another identifier to qualify the signature. The BIN + //checksum is a good candidate. + std::string lvbitx_checksum(_lvbitx->get_bitstream_checksum()); + boost::uint16_t download_fpga = (force_download || (_read_bitstream_checksum() != lvbitx_checksum)) ? 1 : 0; + + nirio_status_chain(_rpc_client.niusrprio_open_session( + _resource_name, bitfile_path, signature, download_fpga), status); + _session_open = nirio_status_not_fatal(status); + + if (nirio_status_not_fatal(status)) { + nirio_register_info_vtr reg_vtr; + nirio_fifo_info_vtr fifo_vtr; + _lvbitx->init_register_info(reg_vtr); + _lvbitx->init_fifo_info(fifo_vtr); + _resource_manager.initialize(reg_vtr, fifo_vtr); + + nirio_status_chain(_verify_signature(), status); + nirio_status_chain(_write_bitstream_checksum(lvbitx_checksum), status); + } + } + + return status; +} + +void niusrprio_session::close(bool skip_reset) +{ + boost::unique_lock<boost::recursive_mutex> lock(_session_mutex); + + if (_session_open) { + nirio_status status = NiRio_Status_Success; + if (!skip_reset) reset(); + nirio_status_chain(_rpc_client.niusrprio_close_session(_resource_name), status); + _session_open = false; + } +} + +nirio_status niusrprio_session::reset() +{ + boost::unique_lock<boost::recursive_mutex> lock(_session_mutex); + return _rpc_client.niusrprio_reset_device(_resource_name); +} + +nirio_status niusrprio_session::download_bitstream_to_flash(const std::string& bitstream_path) +{ + boost::unique_lock<boost::recursive_mutex> lock(_session_mutex); + return _rpc_client.niusrprio_download_fpga_to_flash(_resource_name, bitstream_path); +} + +niriok_proxy::sptr niusrprio_session::create_kernel_proxy( + const std::string& resource_name, + const std::string& rpc_port_name) +{ + usrprio_rpc::usrprio_rpc_client temp_rpc_client("localhost", rpc_port_name); + nirio_status status = temp_rpc_client.get_ctor_status(); + + std::string interface_path; + nirio_status_chain(temp_rpc_client.niusrprio_get_interface_path(resource_name, interface_path), status); + + niriok_proxy::sptr proxy; + if (nirio_status_not_fatal(status)) { + proxy.reset(new niriok_proxy()); + if (proxy) nirio_status_chain(proxy->open(interface_path), status); + } + + return proxy; +} + +nirio_status niusrprio_session::_verify_signature() +{ + //Validate the signature using the kernel proxy + nirio_status status = NiRio_Status_Success; + boost::uint32_t sig_offset = 0; + nirio_status_chain(_riok_proxy.get_attribute(DEFAULT_FPGA_SIGNATURE_OFFSET, sig_offset), status); + niriok_scoped_addr_space(_riok_proxy, FPGA, status); + std::string signature; + for (boost::uint32_t i = 0; i < 8; i++) { + boost::uint32_t quarter_sig; + nirio_status_chain(_riok_proxy.peek(sig_offset, quarter_sig), status); + signature += boost::str(boost::format("%08x") % quarter_sig); + } + + std::string expected_signature(_lvbitx->get_signature()); + boost::to_upper(signature); + boost::to_upper(expected_signature); + if (signature.find(expected_signature) == std::string::npos) { + nirio_status_chain(NiRio_Status_SignatureMismatch, status); + } + + return status; +} + +std::string niusrprio_session::_read_bitstream_checksum() +{ + nirio_status status = NiRio_Status_Success; + niriok_scoped_addr_space(_riok_proxy, BUS_INTERFACE, status); + std::string usr_signature; + for (boost::uint32_t i = 0; i < FPGA_USR_SIG_REG_SIZE; i+=4) { + boost::uint32_t quarter_sig; + nirio_status_chain(_riok_proxy.peek(FPGA_USR_SIG_REG_BASE + i, quarter_sig), status); + usr_signature += boost::str(boost::format("%08x") % quarter_sig); + } + boost::to_upper(usr_signature); + + return usr_signature; +} + +nirio_status niusrprio_session::_write_bitstream_checksum(const std::string& checksum) +{ + nirio_status status = NiRio_Status_Success; + niriok_scoped_addr_space(_riok_proxy, BUS_INTERFACE, status); + for (boost::uint32_t i = 0; i < FPGA_USR_SIG_REG_SIZE; i+=4) { + boost::uint32_t quarter_sig; + try { + std::stringstream ss; + ss << std::hex << checksum.substr(i*2,8); + ss >> quarter_sig; + } catch (std::exception&) { + quarter_sig = 0; + } + nirio_status_chain(_riok_proxy.poke(FPGA_USR_SIG_REG_BASE + i, quarter_sig), status); + } + return status; +} + +}} diff --git a/host/lib/transport/nirio/rpc/CMakeLists.txt b/host/lib/transport/nirio/rpc/CMakeLists.txt new file mode 100644 index 000000000..02c16d2ff --- /dev/null +++ b/host/lib/transport/nirio/rpc/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Copyright 2013 Ettus Research LLC +# +# 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/>. +# + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +######################################################################## +# Append to the list of sources for lib uhd +######################################################################## + +LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/rpc_client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/usrprio_rpc_client.cpp +) diff --git a/host/lib/transport/nirio/rpc/rpc_client.cpp b/host/lib/transport/nirio/rpc/rpc_client.cpp new file mode 100644 index 000000000..a5f8cf412 --- /dev/null +++ b/host/lib/transport/nirio/rpc/rpc_client.cpp @@ -0,0 +1,201 @@ +/// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// + +#include <uhd/transport/nirio/rpc/rpc_client.hpp> +#include <boost/bind.hpp> +#include <boost/format.hpp> + +#define CHAIN_BLOCKING_XFER(func, exp, status) \ + if (status) { \ + status = (static_cast<size_t>((func)) == exp); \ + } else { \ + UHD_LOG << "rpc_client operation skipped: " #func "\n"; \ + } \ + +namespace uhd { namespace usrprio_rpc { + +using boost::asio::ip::tcp; + +rpc_client::rpc_client ( + const std::string& server, + const std::string& port, + boost::uint32_t process_id, + boost::uint32_t host_id +) : _socket(_io_service) +{ + //Fill in handshake info + _hshake_args_client.version = CURRENT_VERSION; + _hshake_args_client.oldest_comp_version = OLDEST_COMPATIBLE_VERSION; + _hshake_args_client.client_id = build_client_id(host_id, process_id); + _hshake_args_client.boost_archive_version = boost_serialization_archive_utils::get_version(); + + try { + //Synchronous resolve + connect + tcp::resolver resolver(_io_service); + tcp::resolver::query query(tcp::v4(), server, port); + tcp::resolver::iterator iterator = resolver.resolve(query); + boost::asio::connect(_socket, iterator); + UHD_LOG << "rpc_client connected to server." << std::endl; + + try { + //Perform handshake + bool status = true; + CHAIN_BLOCKING_XFER( + boost::asio::write(_socket, boost::asio::buffer(&_hshake_args_client, sizeof(_hshake_args_client))), + sizeof(_hshake_args_client), status); + CHAIN_BLOCKING_XFER( + boost::asio::read(_socket, boost::asio::buffer(&_hshake_args_server, sizeof(_hshake_args_server))), + sizeof(_hshake_args_server), status); + + _request.header.client_id = _hshake_args_server.client_id; + + if (_hshake_args_server.version >= _hshake_args_client.oldest_comp_version && + _hshake_args_client.version >= _hshake_args_server.oldest_comp_version && + status) + { + UHD_LOG << "rpc_client bound to server." << std::endl; + _wait_for_next_response_header(); + + //Spawn a thread for the io_service callback handler. This thread will run until rpc_client is destroyed. + _io_service_thread.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, &_io_service))); + } else { + UHD_LOG << "rpc_client handshake failed." << std::endl; + _exec_err.assign(boost::asio::error::connection_refused, boost::system::system_category()); + } + UHD_LOG << boost::format("rpc_client archive = %d, rpc_server archive = %d\n.") % + _hshake_args_client.boost_archive_version % + _hshake_args_server.boost_archive_version; + } catch (boost::exception&) { + UHD_LOG << "rpc_client handshake aborted." << std::endl; + _exec_err.assign(boost::asio::error::connection_refused, boost::system::system_category()); + } + } catch (boost::exception&) { + UHD_LOG << "rpc_client connection request cancelled/aborted." << std::endl; + _exec_err.assign(boost::asio::error::connection_aborted, boost::system::system_category()); + } +} + +rpc_client::~rpc_client () { + _stop_io_service(); +} + +const boost::system::error_code& rpc_client::call( + func_id_t func_id, + const func_args_writer_t& in_args, + func_args_reader_t &out_args, + boost::posix_time::milliseconds timeout +) +{ + boost::mutex::scoped_lock lock(_mutex); + + if (_io_service_thread.get()) { + _request.header.func_id = func_id; + in_args.store(_request.data); + _request.header.func_args_size = _request.data.size(); + + _exec_err.clear(); + + //Send function call header and args + bool status = true; + try { + CHAIN_BLOCKING_XFER( + boost::asio::write(_socket, boost::asio::buffer(&_request.header, sizeof(_request.header))), + sizeof(_request.header), status); + CHAIN_BLOCKING_XFER( + boost::asio::write(_socket, boost::asio::buffer(&(*_request.data.begin()), _request.data.size())), + _request.data.size(), status); + } catch (boost::exception&) { + status = false; + } + + //Wait for response using condition variable + if (status) { + if (!_exec_gate.timed_wait(lock, timeout)) { + UHD_LOG << "rpc_client function timed out." << std::endl; + _exec_err.assign(boost::asio::error::timed_out, boost::system::system_category()); + } + } else { + UHD_LOG << "rpc_client connection dropped." << std::endl; + _exec_err.assign(boost::asio::error::connection_aborted, boost::system::system_category()); + _stop_io_service(); + } + + //Verify that we are talking to the correct endpoint + if ((_request.header.client_id != _response.header.client_id) && !_exec_err) { + UHD_LOG << "rpc_client confused about who its talking to." << std::endl; + _exec_err.assign(boost::asio::error::operation_aborted, boost::system::system_category()); + } + + if (!_exec_err) out_args.load(_response.data); + } + + return _exec_err; +} + +void rpc_client::_handle_response_hdr(const boost::system::error_code& err, size_t transferred, size_t expected) +{ + boost::mutex::scoped_lock lock(_mutex); + _exec_err = err; + if (!_exec_err && (transferred == expected)) { + //Response header received. Verify that it is expected + if (func_args_header_t::match_function(_request.header, _response.header)) { + _response.data.resize(_response.header.func_args_size); + + //Wait for response data + boost::asio::async_read(_socket, + boost::asio::buffer(&(*_response.data.begin()), _response.data.size()), + boost::bind(&rpc_client::_handle_response_data, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred, + _response.data.size())); + } else { + //Unexpected response. Ignore it. + UHD_LOG << "rpc_client received garbage responses." << std::endl; + _exec_err.assign(boost::asio::error::operation_aborted, boost::system::system_category()); + + _wait_for_next_response_header(); + } + } + + if (_exec_err) _exec_gate.notify_all(); +} + +void rpc_client::_handle_response_data(const boost::system::error_code& err, size_t transferred, size_t expected) +{ + boost::mutex::scoped_lock lock(_mutex); + _exec_err = err; + if (transferred != expected) { + _exec_err.assign(boost::asio::error::operation_aborted, boost::system::system_category()); + } + + _exec_gate.notify_all(); + + _wait_for_next_response_header(); +} + +void rpc_client::_wait_for_next_response_header() { + //_mutex must be locked when this call is made + boost::asio::async_read( + _socket, + boost::asio::buffer(&_response.header, sizeof(_response.header)), + boost::bind(&rpc_client::_handle_response_hdr, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred, + sizeof(_response.header))); +} + +}} diff --git a/host/lib/transport/nirio/rpc/usrprio_rpc_client.cpp b/host/lib/transport/nirio/rpc/usrprio_rpc_client.cpp new file mode 100644 index 000000000..1a1f1cd21 --- /dev/null +++ b/host/lib/transport/nirio/rpc/usrprio_rpc_client.cpp @@ -0,0 +1,229 @@ +// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// + +#include <uhd/transport/nirio/rpc/usrprio_rpc_client.hpp> +#include <uhd/utils/platform.hpp> + +namespace uhd { namespace usrprio_rpc { + +usrprio_rpc_client::usrprio_rpc_client( + std::string server, + std::string port +) : _rpc_client(server, port, uhd::get_process_id(), uhd::get_host_id()), + _timeout(boost::posix_time::milliseconds(DEFAULT_TIMEOUT_IN_MS)) +{ + _ctor_status = _rpc_client.status() ? NiRio_Status_RpcConnectionError : NiRio_Status_Success; +} + +usrprio_rpc_client::~usrprio_rpc_client() +{ +} + +nirio_status usrprio_rpc_client::niusrprio_enumerate(NIUSRPRIO_ENUMERATE_ARGS) +/* +#define NIUSRPRIO_ENUMERATE_ARGS \ + usrprio_device_info_vtr& device_info_vtr +*/ +{ + usrprio_rpc::func_args_writer_t in_args; + usrprio_rpc::func_args_reader_t out_args; + nirio_status status = NiRio_Status_Success; + boost::uint32_t vtr_size = 0; + + status = _boost_error_to_nirio_status( + _rpc_client.call(NIUSRPRIO_ENUMERATE, in_args, out_args, _timeout)); + + if (nirio_status_not_fatal(status)) { + out_args >> status; + out_args >> vtr_size; + } + if (nirio_status_not_fatal(status) && vtr_size > 0) { + device_info_vtr.resize(vtr_size); + for (size_t i = 0; i < (size_t)vtr_size; i++) { + usrprio_device_info info; + out_args >> info; + device_info_vtr[i] = info; + } + } + return status; +} + +nirio_status usrprio_rpc_client::niusrprio_open_session(NIUSRPRIO_OPEN_SESSION_ARGS) +/* +#define NIUSRPRIO_OPEN_SESSION_ARGS \ + const std::string& resource, \ + const std::string& path, \ + const std::string& signature, \ + const boost::uint16_t& download_fpga +*/ +{ + usrprio_rpc::func_args_writer_t in_args; + usrprio_rpc::func_args_reader_t out_args; + nirio_status status = NiRio_Status_Success; + + in_args << resource; + in_args << path; + in_args << signature; + in_args << download_fpga; + + //Open needs a longer timeout because the FPGA download can take upto 6 secs and the NiFpga libload can take 4. + static const boost::uint32_t OPEN_TIMEOUT = 15000; + status = _boost_error_to_nirio_status( + _rpc_client.call(NIUSRPRIO_OPEN_SESSION, in_args, out_args, boost::posix_time::milliseconds(OPEN_TIMEOUT))); + + if (nirio_status_not_fatal(status)) { + out_args >> status; + } + + return status; +} + +nirio_status usrprio_rpc_client::niusrprio_close_session(NIUSRPRIO_CLOSE_SESSION_ARGS) +/* +#define NIUSRPRIO_CLOSE_SESSION_ARGS \ + const std::string& resource +*/ +{ + usrprio_rpc::func_args_writer_t in_args; + usrprio_rpc::func_args_reader_t out_args; + nirio_status status = NiRio_Status_Success; + + in_args << resource; + + status = _boost_error_to_nirio_status( + _rpc_client.call(NIUSRPRIO_CLOSE_SESSION, in_args, out_args, _timeout)); + + if (nirio_status_not_fatal(status)) { + out_args >> status; + } + + return status; +} + +nirio_status usrprio_rpc_client::niusrprio_reset_device(NIUSRPRIO_RESET_SESSION_ARGS) +/* +#define NIUSRPRIO_RESET_SESSION_ARGS \ + const std::string& resource +*/ +{ + usrprio_rpc::func_args_writer_t in_args; + usrprio_rpc::func_args_reader_t out_args; + nirio_status status = NiRio_Status_Success; + + in_args << resource; + + status = _boost_error_to_nirio_status( + _rpc_client.call(NIUSRPRIO_RESET_SESSION, in_args, out_args, _timeout)); + + if (nirio_status_not_fatal(status)) { + out_args >> status; + } + + return status; +} + +nirio_status usrprio_rpc_client::niusrprio_get_interface_path(NIUSRPRIO_GET_INTERFACE_PATH_ARGS) +/* +#define NIUSRPRIO_GET_INTERFACE_PATH_ARGS \ + const std::string& resource, \ + std::string& interface_path +*/ +{ + usrprio_rpc::func_args_writer_t in_args; + usrprio_rpc::func_args_reader_t out_args; + nirio_status status = NiRio_Status_Success; + + in_args << resource; + + status = _boost_error_to_nirio_status( + _rpc_client.call(NIUSRPRIO_GET_INTERFACE_PATH, in_args, out_args, _timeout)); + + if (nirio_status_not_fatal(status)) { + out_args >> status; + out_args >> interface_path; + } + + return status; +} + +nirio_status usrprio_rpc_client::niusrprio_download_fpga_to_flash(NIUSRPRIO_DOWNLOAD_FPGA_TO_FLASH_ARGS) +/* +#define NIUSRPRIO_DOWNLOAD_FPGA_TO_FLASH_ARGS \ + const boost::uint32_t& interface_num, \ + const std::string& bitstream_path +*/ +{ + usrprio_rpc::func_args_writer_t in_args; + usrprio_rpc::func_args_reader_t out_args; + nirio_status status = NiRio_Status_Success; + + in_args << resource; + in_args << bitstream_path; + + static const boost::uint32_t DOWNLOAD_FPGA_TIMEOUT = 1200000; + status = _boost_error_to_nirio_status( + _rpc_client.call(NIUSRPRIO_DOWNLOAD_FPGA_TO_FLASH, in_args, out_args, + boost::posix_time::milliseconds(DOWNLOAD_FPGA_TIMEOUT))); + + if (nirio_status_not_fatal(status)) { + out_args >> status; + } + + return status; +} + +nirio_status usrprio_rpc_client::niusrprio_download_bitstream_to_fpga(NIUSRPRIO_DOWNLOAD_BITSTREAM_TO_FPGA_ARGS) +/* +#define NIUSRPRIO_DOWNLOAD_BITSTREAM_TO_FPGA_ARGS \ + const std::string& resource +*/ +{ + usrprio_rpc::func_args_writer_t in_args; + usrprio_rpc::func_args_reader_t out_args; + nirio_status status = NiRio_Status_Success; + + in_args << resource; + + status = _boost_error_to_nirio_status( + _rpc_client.call(NIUSRPRIO_DOWNLOAD_BITSTREAM_TO_FPGA, in_args, out_args, _timeout)); + + if (nirio_status_not_fatal(status)) { + out_args >> status; + } + + return status; +} + +nirio_status usrprio_rpc_client::_boost_error_to_nirio_status(const boost::system::error_code& err) { + if (err) { + switch (err.value()) { + case boost::asio::error::connection_aborted: + case boost::asio::error::connection_refused: + case boost::asio::error::eof: + return NiRio_Status_RpcSessionError; + case boost::asio::error::timed_out: + case boost::asio::error::operation_aborted: + return NiRio_Status_RpcOperationError; + default: + return NiRio_Status_SoftwareFault; + } + } else { + return NiRio_Status_Success; + } +} + +}} diff --git a/host/lib/transport/nirio/status.cpp b/host/lib/transport/nirio/status.cpp new file mode 100644 index 000000000..f3f8d4cd1 --- /dev/null +++ b/host/lib/transport/nirio/status.cpp @@ -0,0 +1,55 @@ +// +// Copyright 2013 Ettus Research LLC +// +// 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/>. +// + + +#include <uhd/transport/nirio/status.h> +#include <boost/format.hpp> + +namespace uhd { namespace niusrprio { + +#define NIRIO_ERR_INFO(CONST_NAME, ERR_CODE, ERR_MSG) \ + nirio_err_info(ERR_CODE, ERR_MSG), + +const nirio_err_info nirio_err_info::NIRIO_ERROR_TABLE[] = { + #include "../../../include/uhd/transport/nirio/nirio_err_template.h" +}; + +#undef NIRIO_ERR_INFO + +const size_t nirio_err_info::NIRIO_ERROR_TABLE_SIZE = sizeof(NIRIO_ERROR_TABLE)/sizeof(*NIRIO_ERROR_TABLE); + +const std::string lookup_err_msg(nirio_status code) { + std::string error_msg = (boost::format("Unknown error. (Error code %d)") % code).str(); + for (size_t i = 0; i < nirio_err_info::NIRIO_ERROR_TABLE_SIZE; i++) { + if (nirio_err_info::NIRIO_ERROR_TABLE[i].code == code) { + error_msg = (boost::format("%s (Error code %d)") % nirio_err_info::NIRIO_ERROR_TABLE[i].msg % code).str(); + break; + } + } + return error_msg; +} + +void nirio_status_to_exception(const nirio_status& status, const std::string& message) { + if (nirio_status_fatal(status)) { + throw uhd::runtime_error((boost::format("%s %s") % message % lookup_err_msg(status)).str()); + } +} + +}} + + + |