aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/transport/nirio
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/transport/nirio')
-rw-r--r--host/lib/transport/nirio/CMakeLists.txt48
-rw-r--r--host/lib/transport/nirio/lvbitx/CMakeLists.txt65
-rwxr-xr-xhost/lib/transport/nirio/lvbitx/process-lvbitx.py185
-rw-r--r--host/lib/transport/nirio/lvbitx/template_lvbitx.cpp86
-rw-r--r--host/lib/transport/nirio/lvbitx/template_lvbitx.hpp48
-rwxr-xr-xhost/lib/transport/nirio/lvbitx/x300.lvbitx_base469
-rwxr-xr-xhost/lib/transport/nirio/lvbitx/x310.lvbitx_base469
-rw-r--r--host/lib/transport/nirio/nifpga_lvbitx.cpp138
-rw-r--r--host/lib/transport/nirio/nirio_driver_iface_linux.cpp111
-rw-r--r--host/lib/transport/nirio/nirio_driver_iface_macos.cpp63
-rw-r--r--host/lib/transport/nirio/nirio_driver_iface_win.cpp148
-rw-r--r--host/lib/transport/nirio/nirio_resource_manager.cpp120
-rw-r--r--host/lib/transport/nirio/niriok_proxy.cpp300
-rw-r--r--host/lib/transport/nirio/niusrprio_session.cpp199
-rw-r--r--host/lib/transport/nirio/rpc/CMakeLists.txt29
-rw-r--r--host/lib/transport/nirio/rpc/rpc_client.cpp201
-rw-r--r--host/lib/transport/nirio/rpc/usrprio_rpc_client.cpp229
-rw-r--r--host/lib/transport/nirio/status.cpp55
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());
+ }
+}
+
+}}
+
+
+