From d743784919b362d93e6408f05bdef6e543e3fc7e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 8 Apr 2010 10:57:16 -0700 Subject: converted timespec to use nanoseconds for fractional part --- host/lib/transport/gen_vrt.py | 10 +++--- host/lib/transport/vrt.cpp | 72 ++++++++++++++++++++++--------------------- 2 files changed, 43 insertions(+), 39 deletions(-) (limited to 'host/lib/transport') diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py index 918de3ad7..bc6635d78 100755 --- a/host/lib/transport/gen_vrt.py +++ b/host/lib/transport/gen_vrt.py @@ -54,7 +54,8 @@ void vrt::pack( size_t &num_header_words32, //output size_t num_payload_words32, //input size_t &num_packet_words32, //output - size_t packet_count //input + size_t packet_count, //input + double tick_rate //input ){ boost::uint32_t vrt_hdr_flags; @@ -91,7 +92,7 @@ void vrt::pack( #if $pred & $tsf_p header_buff[$num_header_words] = htonl(0); #set $num_header_words += 1 - header_buff[$num_header_words] = htonl(metadata.time_spec.ticks); + header_buff[$num_header_words] = htonl(metadata.time_spec.get_ticks(tick_rate)); #set $num_header_words += 1 #set $flags |= (0x1 << 20); #end if @@ -127,7 +128,8 @@ void vrt::unpack( size_t &num_header_words32, //output size_t &num_payload_words32, //output size_t num_packet_words32, //input - size_t &packet_count //output + size_t &packet_count, //output + double tick_rate //input ){ //clear the metadata metadata = rx_metadata_t(); @@ -180,7 +182,7 @@ void vrt::unpack( #set $set_has_time_spec = True #end if #set $num_header_words += 1 - metadata.time_spec.ticks = ntohl(header_buff[$num_header_words]); + metadata.time_spec.set_ticks(ntohl(header_buff[$num_header_words]), tick_rate); #set $num_header_words += 1 #end if ########## Trailer ########## diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp index bebca5db9..78c3cf2cb 100644 --- a/host/lib/transport/vrt.cpp +++ b/host/lib/transport/vrt.cpp @@ -2,7 +2,7 @@ /*********************************************************************** - * This file was generated by ./gen_vrt.py on Fri Mar 26 15:33:00 2010 + * This file was generated by gen_vrt.py on 04/08/10 10:55:26 **********************************************************************/ #include @@ -18,7 +18,8 @@ void vrt::pack( size_t &num_header_words32, //output size_t num_payload_words32, //input size_t &num_packet_words32, //output - size_t packet_count //input + size_t packet_count, //input + double tick_rate //input ){ boost::uint32_t vrt_hdr_flags; @@ -85,7 +86,7 @@ void vrt::pack( break; case 8: header_buff[1] = htonl(0); - header_buff[2] = htonl(metadata.time_spec.ticks); + header_buff[2] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 3; num_packet_words32 = 3 + num_payload_words32; vrt_hdr_flags = 0x100000; @@ -93,7 +94,7 @@ void vrt::pack( case 9: header_buff[1] = htonl(metadata.stream_id); header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.ticks); + header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 4; num_packet_words32 = 4 + num_payload_words32; vrt_hdr_flags = 0x10100000; @@ -102,7 +103,7 @@ void vrt::pack( header_buff[1] = htonl(0); header_buff[2] = htonl(0); header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.ticks); + header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 5; num_packet_words32 = 5 + num_payload_words32; vrt_hdr_flags = 0x8100000; @@ -112,7 +113,7 @@ void vrt::pack( header_buff[2] = htonl(0); header_buff[3] = htonl(0); header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.ticks); + header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 6; num_packet_words32 = 6 + num_payload_words32; vrt_hdr_flags = 0x18100000; @@ -120,7 +121,7 @@ void vrt::pack( case 12: header_buff[1] = htonl(metadata.time_spec.secs); header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.ticks); + header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 4; num_packet_words32 = 4 + num_payload_words32; vrt_hdr_flags = 0xd00000; @@ -129,7 +130,7 @@ void vrt::pack( header_buff[1] = htonl(metadata.stream_id); header_buff[2] = htonl(metadata.time_spec.secs); header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.ticks); + header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 5; num_packet_words32 = 5 + num_payload_words32; vrt_hdr_flags = 0x10d00000; @@ -139,7 +140,7 @@ void vrt::pack( header_buff[2] = htonl(0); header_buff[3] = htonl(metadata.time_spec.secs); header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.ticks); + header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 6; num_packet_words32 = 6 + num_payload_words32; vrt_hdr_flags = 0x8d00000; @@ -150,7 +151,7 @@ void vrt::pack( header_buff[3] = htonl(0); header_buff[4] = htonl(metadata.time_spec.secs); header_buff[5] = htonl(0); - header_buff[6] = htonl(metadata.time_spec.ticks); + header_buff[6] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 7; num_packet_words32 = 7 + num_payload_words32; vrt_hdr_flags = 0x18d00000; @@ -213,7 +214,7 @@ void vrt::pack( break; case 24: header_buff[1] = htonl(0); - header_buff[2] = htonl(metadata.time_spec.ticks); + header_buff[2] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 3; num_packet_words32 = 4 + num_payload_words32; vrt_hdr_flags = 0x4100000; @@ -221,7 +222,7 @@ void vrt::pack( case 25: header_buff[1] = htonl(metadata.stream_id); header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.ticks); + header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 4; num_packet_words32 = 5 + num_payload_words32; vrt_hdr_flags = 0x14100000; @@ -230,7 +231,7 @@ void vrt::pack( header_buff[1] = htonl(0); header_buff[2] = htonl(0); header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.ticks); + header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 5; num_packet_words32 = 6 + num_payload_words32; vrt_hdr_flags = 0xc100000; @@ -240,7 +241,7 @@ void vrt::pack( header_buff[2] = htonl(0); header_buff[3] = htonl(0); header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.ticks); + header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 6; num_packet_words32 = 7 + num_payload_words32; vrt_hdr_flags = 0x1c100000; @@ -248,7 +249,7 @@ void vrt::pack( case 28: header_buff[1] = htonl(metadata.time_spec.secs); header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.ticks); + header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 4; num_packet_words32 = 5 + num_payload_words32; vrt_hdr_flags = 0x4d00000; @@ -257,7 +258,7 @@ void vrt::pack( header_buff[1] = htonl(metadata.stream_id); header_buff[2] = htonl(metadata.time_spec.secs); header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.ticks); + header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 5; num_packet_words32 = 6 + num_payload_words32; vrt_hdr_flags = 0x14d00000; @@ -267,7 +268,7 @@ void vrt::pack( header_buff[2] = htonl(0); header_buff[3] = htonl(metadata.time_spec.secs); header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.ticks); + header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 6; num_packet_words32 = 7 + num_payload_words32; vrt_hdr_flags = 0xcd00000; @@ -278,7 +279,7 @@ void vrt::pack( header_buff[3] = htonl(0); header_buff[4] = htonl(metadata.time_spec.secs); header_buff[5] = htonl(0); - header_buff[6] = htonl(metadata.time_spec.ticks); + header_buff[6] = htonl(metadata.time_spec.get_ticks(tick_rate)); num_header_words32 = 7; num_packet_words32 = 8 + num_payload_words32; vrt_hdr_flags = 0x1cd00000; @@ -302,7 +303,8 @@ void vrt::unpack( size_t &num_header_words32, //output size_t &num_payload_words32, //output size_t num_packet_words32, //input - size_t &packet_count //output + size_t &packet_count, //output + double tick_rate //input ){ //clear the metadata metadata = rx_metadata_t(); @@ -376,7 +378,7 @@ void vrt::unpack( break; case 8: metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[2]); + metadata.time_spec.set_ticks(ntohl(header_buff[2]), tick_rate); num_header_words32 = 3; num_payload_words32 = packet_words32 - 3; break; @@ -384,13 +386,13 @@ void vrt::unpack( metadata.has_stream_id = true; metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[3]); + metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); num_header_words32 = 4; num_payload_words32 = packet_words32 - 4; break; case 10: metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[4]); + metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); num_header_words32 = 5; num_payload_words32 = packet_words32 - 5; break; @@ -398,14 +400,14 @@ void vrt::unpack( metadata.has_stream_id = true; metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[5]); + metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); num_header_words32 = 6; num_payload_words32 = packet_words32 - 6; break; case 12: metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[1]); - metadata.time_spec.ticks = ntohl(header_buff[3]); + metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); num_header_words32 = 4; num_payload_words32 = packet_words32 - 4; break; @@ -414,14 +416,14 @@ void vrt::unpack( metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[2]); - metadata.time_spec.ticks = ntohl(header_buff[4]); + metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); num_header_words32 = 5; num_payload_words32 = packet_words32 - 5; break; case 14: metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[3]); - metadata.time_spec.ticks = ntohl(header_buff[5]); + metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); num_header_words32 = 6; num_payload_words32 = packet_words32 - 6; break; @@ -430,7 +432,7 @@ void vrt::unpack( metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[4]); - metadata.time_spec.ticks = ntohl(header_buff[6]); + metadata.time_spec.set_ticks(ntohl(header_buff[6]), tick_rate); num_header_words32 = 7; num_payload_words32 = packet_words32 - 7; break; @@ -484,7 +486,7 @@ void vrt::unpack( break; case 24: metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[2]); + metadata.time_spec.set_ticks(ntohl(header_buff[2]), tick_rate); num_header_words32 = 3; num_payload_words32 = packet_words32 - 4; break; @@ -492,13 +494,13 @@ void vrt::unpack( metadata.has_stream_id = true; metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[3]); + metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); num_header_words32 = 4; num_payload_words32 = packet_words32 - 5; break; case 26: metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[4]); + metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); num_header_words32 = 5; num_payload_words32 = packet_words32 - 6; break; @@ -506,14 +508,14 @@ void vrt::unpack( metadata.has_stream_id = true; metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[5]); + metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); num_header_words32 = 6; num_payload_words32 = packet_words32 - 7; break; case 28: metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[1]); - metadata.time_spec.ticks = ntohl(header_buff[3]); + metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); num_header_words32 = 4; num_payload_words32 = packet_words32 - 5; break; @@ -522,14 +524,14 @@ void vrt::unpack( metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[2]); - metadata.time_spec.ticks = ntohl(header_buff[4]); + metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); num_header_words32 = 5; num_payload_words32 = packet_words32 - 6; break; case 30: metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[3]); - metadata.time_spec.ticks = ntohl(header_buff[5]); + metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); num_header_words32 = 6; num_payload_words32 = packet_words32 - 7; break; @@ -538,7 +540,7 @@ void vrt::unpack( metadata.stream_id = ntohl(header_buff[1]); metadata.has_time_spec = true; metadata.time_spec.secs = ntohl(header_buff[4]); - metadata.time_spec.ticks = ntohl(header_buff[6]); + metadata.time_spec.set_ticks(ntohl(header_buff[6]), tick_rate); num_header_words32 = 7; num_payload_words32 = packet_words32 - 8; break; -- cgit v1.2.3 From fdd80e548dcda3e4ee0c022d7d04b5ba581c5ad9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 9 Apr 2010 08:13:19 -0700 Subject: added python+cheetah build requirement, generating vrt.cpp --- host/CMakeLists.txt | 20 +- host/lib/CMakeLists.txt | 46 +++- host/lib/transport/gen_vrt.py | 3 +- host/lib/transport/vrt.cpp | 549 ------------------------------------------ 4 files changed, 57 insertions(+), 561 deletions(-) delete mode 100644 host/lib/transport/vrt.cpp (limited to 'host/lib/transport') diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index baae90861..6334b44ff 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -25,8 +25,8 @@ ENABLE_TESTING() SET(CPACK_PACKAGE_VERSION_MAJOR 0) SET(CPACK_PACKAGE_VERSION_MINOR 0) SET(CPACK_PACKAGE_VERSION_PATCH 0) -SET(CPACK_RESOURCE_FILE_README ${CMAKE_SOURCE_DIR}/README) -SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE) +SET(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README) +SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) INCLUDE(CPack) #include after setting vars ######################################################################## @@ -42,18 +42,18 @@ MESSAGE(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") ######################################################################## # Local Include Dir ######################################################################## -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) ######################################################################## # Optional Compiler Flags ######################################################################## INCLUDE(CheckCXXCompilerFlag) -FUNCTION(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG flag have) +MACRO(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG flag have) CHECK_CXX_COMPILER_FLAG(${flag} ${have}) IF(${have}) ADD_DEFINITIONS(${flag}) ENDIF(${have}) -ENDFUNCTION(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG) +ENDMACRO(UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG) IF(UNIX) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wall HAVE_WALL) @@ -114,7 +114,7 @@ ADD_CUSTOM_TARGET(uninstall # Create Pkg Config File ######################################################################## CONFIGURE_FILE( - ${CMAKE_SOURCE_DIR}/uhd.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/uhd.pc.in ${CMAKE_CURRENT_BINARY_DIR}/uhd.pc @ONLY) @@ -131,7 +131,7 @@ INCLUDE(FindDoxygen) IF(DOXYGEN_FOUND) SET(CMAKE_CURRENT_BINARY_DIR_DOXYGEN ${CMAKE_CURRENT_BINARY_DIR}/doxygen) CONFIGURE_FILE( - ${CMAKE_SOURCE_DIR}/Doxyfile.in + ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR_DOXYGEN} @@ -143,9 +143,9 @@ IF(DOXYGEN_FOUND) ENDIF(DOXYGEN_FOUND) INSTALL(FILES - ${CMAKE_SOURCE_DIR}/README - ${CMAKE_SOURCE_DIR}/LICENSE - ${CMAKE_SOURCE_DIR}/AUTHORS + ${CMAKE_CURRENT_SOURCE_DIR}/README + ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE + ${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS DESTINATION ${PKG_DOC_DIR} ) diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index f21a4a491..87e35f412 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -15,6 +15,33 @@ # along with this program. If not, see . # + +######################################################################## +# Setup Python +######################################################################## +INCLUDE(FindPythonInterp) + +MACRO(PYTHON_CHECK_MODULE module have) + MESSAGE(STATUS "Checking for python module ${module}") + EXECUTE_PROCESS( + COMMAND ${PYTHON_EXECUTABLE} -c "import ${module}" + RESULT_VARIABLE ${have} + ) + IF(${have} EQUAL 0) + MESSAGE(STATUS "Checking for python module ${module} - found") + SET(${have} TRUE) + ELSE(${have} EQUAL 0) + MESSAGE(STATUS "Checking for python module ${module} - not found") + SET(${have} FALSE) + ENDIF(${have} EQUAL 0) +ENDMACRO(PYTHON_CHECK_MODULE) + +PYTHON_CHECK_MODULE("Cheetah" HAVE_PYTHON_MODULE_CHEETAH) + +IF(NOT HAVE_PYTHON_MODULE_CHEETAH) + MESSAGE(FATAL_ERROR "Error: Cheetah Templates needed for pre-build generation.") +ENDIF(NOT HAVE_PYTHON_MODULE_CHEETAH) + ######################################################################## # Create a list of libuhd sources ######################################################################## @@ -26,7 +53,6 @@ SET(libuhd_sources wax.cpp transport/if_addrs.cpp transport/udp_simple.cpp - transport/vrt.cpp usrp/dboard/db_basic_and_lf.cpp usrp/dboard/db_rfx.cpp usrp/dboard_base.cpp @@ -41,6 +67,24 @@ SET(libuhd_sources usrp/usrp2/usrp2_impl.cpp ) +######################################################################## +# Generate Files +######################################################################## +MACRO(UHD_PYTHON_GEN_FILE pyfile outfile) + ADD_CUSTOM_COMMAND( + OUTPUT ${outfile} DEPENDS ${pyfile} + COMMAND ${PYTHON_EXECUTABLE} ${pyfile} ${outfile} + COMMENT "Calling ${pyfile} to generate ${outfile}" + ) +ENDMACRO(UHD_PYTHON_GEN_FILE) +UHD_PYTHON_GEN_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/transport/gen_vrt.py + ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp +) +LIST(APPEND libuhd_sources + ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp +) + ######################################################################## # Conditionally add the udp sources ######################################################################## diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py index bc6635d78..0f961efc2 100755 --- a/host/lib/transport/gen_vrt.py +++ b/host/lib/transport/gen_vrt.py @@ -200,9 +200,10 @@ void vrt::unpack( } """ +import sys from Cheetah import Template def parse_str(_tmpl_text, **kwargs): return str(Template.Template(_tmpl_text, kwargs)) if __name__ == '__main__': from Cheetah import Template - print parse_str(TMPL_TEXT, file=__file__) + open(sys.argv[1], 'w').write(parse_str(TMPL_TEXT, file=__file__)) diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp deleted file mode 100644 index 78c3cf2cb..000000000 --- a/host/lib/transport/vrt.cpp +++ /dev/null @@ -1,549 +0,0 @@ - - - -/*********************************************************************** - * This file was generated by gen_vrt.py on 04/08/10 10:55:26 - **********************************************************************/ - -#include -#include //endianness conversion -#include - -using namespace uhd; -using namespace uhd::transport; - -void vrt::pack( - const tx_metadata_t &metadata, //input - boost::uint32_t *header_buff, //output - size_t &num_header_words32, //output - size_t num_payload_words32, //input - size_t &num_packet_words32, //output - size_t packet_count, //input - double tick_rate //input -){ - boost::uint32_t vrt_hdr_flags; - - boost::uint8_t pred = 0; - if (metadata.has_stream_id) pred |= 0x1; - if (metadata.has_time_spec) pred |= 0xc; - - switch(pred){ - case 0: - num_header_words32 = 1; - num_packet_words32 = 1 + num_payload_words32; - vrt_hdr_flags = 0x0; - break; - case 1: - header_buff[1] = htonl(metadata.stream_id); - num_header_words32 = 2; - num_packet_words32 = 2 + num_payload_words32; - vrt_hdr_flags = 0x10000000; - break; - case 2: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - num_header_words32 = 3; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x8000000; - break; - case 3: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x18000000; - break; - case 4: - header_buff[1] = htonl(metadata.time_spec.secs); - num_header_words32 = 2; - num_packet_words32 = 2 + num_payload_words32; - vrt_hdr_flags = 0xc00000; - break; - case 5: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - num_header_words32 = 3; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x10c00000; - break; - case 6: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x8c00000; - break; - case 7: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - num_header_words32 = 5; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x18c00000; - break; - case 8: - header_buff[1] = htonl(0); - header_buff[2] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 3; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x100000; - break; - case 9: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x10100000; - break; - case 10: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x8100000; - break; - case 11: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x18100000; - break; - case 12: - header_buff[1] = htonl(metadata.time_spec.secs); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0xd00000; - break; - case 13: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x10d00000; - break; - case 14: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x8d00000; - break; - case 15: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - header_buff[5] = htonl(0); - header_buff[6] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 7; - num_packet_words32 = 7 + num_payload_words32; - vrt_hdr_flags = 0x18d00000; - break; - case 16: - num_header_words32 = 1; - num_packet_words32 = 2 + num_payload_words32; - vrt_hdr_flags = 0x4000000; - break; - case 17: - header_buff[1] = htonl(metadata.stream_id); - num_header_words32 = 2; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x14000000; - break; - case 18: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - num_header_words32 = 3; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0xc000000; - break; - case 19: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x1c000000; - break; - case 20: - header_buff[1] = htonl(metadata.time_spec.secs); - num_header_words32 = 2; - num_packet_words32 = 3 + num_payload_words32; - vrt_hdr_flags = 0x4c00000; - break; - case 21: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - num_header_words32 = 3; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x14c00000; - break; - case 22: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0xcc00000; - break; - case 23: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - num_header_words32 = 5; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x1cc00000; - break; - case 24: - header_buff[1] = htonl(0); - header_buff[2] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 3; - num_packet_words32 = 4 + num_payload_words32; - vrt_hdr_flags = 0x4100000; - break; - case 25: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x14100000; - break; - case 26: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0xc100000; - break; - case 27: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 7 + num_payload_words32; - vrt_hdr_flags = 0x1c100000; - break; - case 28: - header_buff[1] = htonl(metadata.time_spec.secs); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 4; - num_packet_words32 = 5 + num_payload_words32; - vrt_hdr_flags = 0x4d00000; - break; - case 29: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(metadata.time_spec.secs); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 5; - num_packet_words32 = 6 + num_payload_words32; - vrt_hdr_flags = 0x14d00000; - break; - case 30: - header_buff[1] = htonl(0); - header_buff[2] = htonl(0); - header_buff[3] = htonl(metadata.time_spec.secs); - header_buff[4] = htonl(0); - header_buff[5] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 6; - num_packet_words32 = 7 + num_payload_words32; - vrt_hdr_flags = 0xcd00000; - break; - case 31: - header_buff[1] = htonl(metadata.stream_id); - header_buff[2] = htonl(0); - header_buff[3] = htonl(0); - header_buff[4] = htonl(metadata.time_spec.secs); - header_buff[5] = htonl(0); - header_buff[6] = htonl(metadata.time_spec.get_ticks(tick_rate)); - num_header_words32 = 7; - num_packet_words32 = 8 + num_payload_words32; - vrt_hdr_flags = 0x1cd00000; - break; - } - - //set the burst flags - if (metadata.start_of_burst) vrt_hdr_flags |= 0x2000000; - if (metadata.end_of_burst) vrt_hdr_flags |= 0x1000000; - - //fill in complete header word - header_buff[0] = htonl(vrt_hdr_flags | - ((packet_count & 0xf) << 16) | - (num_packet_words32 & 0xffff) - ); -} - -void vrt::unpack( - rx_metadata_t &metadata, //output - const boost::uint32_t *header_buff, //input - size_t &num_header_words32, //output - size_t &num_payload_words32, //output - size_t num_packet_words32, //input - size_t &packet_count, //output - double tick_rate //input -){ - //clear the metadata - metadata = rx_metadata_t(); - - //extract vrt header - boost::uint32_t vrt_hdr_word = ntohl(header_buff[0]); - size_t packet_words32 = vrt_hdr_word & 0xffff; - packet_count = (vrt_hdr_word >> 16) & 0xf; - - //failure cases - if (packet_words32 == 0 or num_packet_words32 < packet_words32) - throw std::runtime_error("bad vrt header or packet fragment"); - if (vrt_hdr_word & (0x7 << 29)) - throw std::runtime_error("unsupported vrt packet type"); - - boost::uint8_t pred = 0; - if(vrt_hdr_word & 0x10000000) pred |= 0x1; - if(vrt_hdr_word & 0x8000000) pred |= 0x2; - if(vrt_hdr_word & 0xc00000) pred |= 0x4; - if(vrt_hdr_word & 0x300000) pred |= 0x8; - if(vrt_hdr_word & 0x4000000) pred |= 0x10; - - switch(pred){ - case 0: - num_header_words32 = 1; - num_payload_words32 = packet_words32 - 1; - break; - case 1: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 2; - break; - case 2: - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 3; - break; - case 3: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 4: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 2; - break; - case 5: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 3; - break; - case 6: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 7: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 5; - break; - case 8: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[2]), tick_rate); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 3; - break; - case 9: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 10: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 5; - break; - case 11: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 6; - break; - case 12: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 4; - break; - case 13: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 5; - break; - case 14: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 6; - break; - case 15: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - metadata.time_spec.set_ticks(ntohl(header_buff[6]), tick_rate); - num_header_words32 = 7; - num_payload_words32 = packet_words32 - 7; - break; - case 16: - num_header_words32 = 1; - num_payload_words32 = packet_words32 - 2; - break; - case 17: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 3; - break; - case 18: - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 4; - break; - case 19: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 20: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - num_header_words32 = 2; - num_payload_words32 = packet_words32 - 3; - break; - case 21: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 4; - break; - case 22: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 23: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 6; - break; - case 24: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[2]), tick_rate); - num_header_words32 = 3; - num_payload_words32 = packet_words32 - 4; - break; - case 25: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 26: - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 6; - break; - case 27: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 7; - break; - case 28: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[1]); - metadata.time_spec.set_ticks(ntohl(header_buff[3]), tick_rate); - num_header_words32 = 4; - num_payload_words32 = packet_words32 - 5; - break; - case 29: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[2]); - metadata.time_spec.set_ticks(ntohl(header_buff[4]), tick_rate); - num_header_words32 = 5; - num_payload_words32 = packet_words32 - 6; - break; - case 30: - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[3]); - metadata.time_spec.set_ticks(ntohl(header_buff[5]), tick_rate); - num_header_words32 = 6; - num_payload_words32 = packet_words32 - 7; - break; - case 31: - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[1]); - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[4]); - metadata.time_spec.set_ticks(ntohl(header_buff[6]), tick_rate); - num_header_words32 = 7; - num_payload_words32 = packet_words32 - 8; - break; - } -} - -- cgit v1.2.3 From 0021abf18aaf3831d8aaa40574f1876c4f346a92 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 12:22:29 -0700 Subject: Created zero copy interface/framework, made use of it in usrp2 udp transport stuff. --- host/include/uhd/transport/CMakeLists.txt | 2 +- host/include/uhd/transport/smart_buffer.hpp | 45 --------- host/include/uhd/transport/udp_zero_copy.hpp | 28 +----- host/include/uhd/transport/zero_copy.hpp | 133 +++++++++++++++++++++++++++ host/lib/transport/udp_zero_copy_asio.cpp | 105 ++++++++++++++------- host/lib/usrp/usrp2/io_impl.cpp | 21 +++-- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 +- 7 files changed, 223 insertions(+), 113 deletions(-) delete mode 100644 host/include/uhd/transport/smart_buffer.hpp create mode 100644 host/include/uhd/transport/zero_copy.hpp (limited to 'host/lib/transport') diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 14b5ccd29..9a94ead1b 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -18,9 +18,9 @@ INSTALL(FILES if_addrs.hpp - smart_buffer.hpp udp_simple.hpp udp_zero_copy.hpp vrt.hpp + zero_copy.hpp DESTINATION ${INCLUDE_DIR}/uhd/transport ) diff --git a/host/include/uhd/transport/smart_buffer.hpp b/host/include/uhd/transport/smart_buffer.hpp deleted file mode 100644 index a9bc259e9..000000000 --- a/host/include/uhd/transport/smart_buffer.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright 2010 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 . -// - -#ifndef INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP -#define INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP - -#include -#include -#include - -namespace uhd{ namespace transport{ - -/*! - * A buffer that knows how to free itself: - * - * This is just the smart buffer interface. - * A transport implementation will have its own - * internal (custom) smart buffer implementation. - * - * A smart buffer contains a boost asio const buffer. - * On destruction, the buffer contents will be freed. - */ -class smart_buffer : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - virtual const boost::asio::const_buffer &get(void) const = 0; -}; - -}} //namespace - -#endif /* INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP */ diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index 0441a8e74..fd1cec46e 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -19,24 +19,22 @@ #define INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP #include -#include -#include -#include +#include #include namespace uhd{ namespace transport{ /*! * A zero copy udp transport provides an efficient way to handle data. - * by avoiding the extra copy when recv() is called on the socket. - * Rather, the zero copy transport gives the caller a memory reference. + * by avoiding the extra copy when recv() or send() is called on the socket. + * Rather, the zero copy transport gives the caller memory references. * The caller informs the transport when it is finished with the reference. * * On linux systems, the zero copy transport can use a kernel packet ring. * If no platform specific solution is available, make returns a boost asio - * implementation that wraps the functionality around a standard recv() call. + * implementation that wraps the functionality around a standard send/recv calls. */ -class UHD_API udp_zero_copy : boost::noncopyable{ +class UHD_API udp_zero_copy : public zero_copy_if{ public: typedef boost::shared_ptr sptr; @@ -54,22 +52,6 @@ public: * \param port a string representing the destination port */ static sptr make(const std::string &addr, const std::string &port); - - /*! - * Send a single buffer. - * Blocks until the data is sent. - * \param buff single asio buffer - * \return the number of bytes sent - */ - virtual size_t send(const boost::asio::const_buffer &buff) = 0; - - /*! - * Receive a buffer. - * Blocks until data is received or a timeout occurs. - * The memory is managed by the implementation. - * \return a smart buffer (empty on timeout) - */ - virtual smart_buffer::sptr recv(void) = 0; }; }} //namespace diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp new file mode 100644 index 000000000..4fc1df9de --- /dev/null +++ b/host/include/uhd/transport/zero_copy.hpp @@ -0,0 +1,133 @@ +// +// Copyright 2010 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 . +// + +#ifndef INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP + +#include +#include +#include +#include + +namespace uhd{ namespace transport{ + +/*! + * A managed receive buffer: + * Contains a reference to transport-managed memory, + * and a method to release the memory after reading. + */ +class UHD_API managed_recv_buffer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Signal to the transport that we are done with the buffer. + * This should be called to release the buffer to the transport. + * After calling, the referenced memory should be considered invalid. + */ + virtual void done(void) = 0; + + /*! + * Get the size of the underlying buffer. + * \return the number of bytes + */ + size_t size(void){ + return boost::asio::buffer_size(this->get()); + } + + /*! + * Get a pointer to the underlying buffer. + * \return a pointer into memory + */ + template T cast(void){ + return boost::asio::buffer_cast(this->get()); + } + +private: + /*! + * Get a reference to the internal const buffer. + * The buffer has a reference to memory and a size. + * \return a boost asio const buffer + */ + virtual const boost::asio::const_buffer &get(void) = 0; +}; + +/*! + * A managed send buffer: + * Contains a reference to transport-managed memory, + * and a method to release the memory after writing. + */ +class UHD_API managed_send_buffer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Signal to the transport that we are done with the buffer. + * This should be called to commit the write to the transport object. + * After calling, the referenced memory should be considered invalid. + * \param num_bytes the number of bytes written into the buffer + */ + virtual void done(size_t num_bytes) = 0; + + /*! + * Get the size of the underlying buffer. + * \return the number of bytes + */ + size_t size(void){ + return boost::asio::buffer_size(this->get()); + } + + /*! + * Get a pointer to the underlying buffer. + * \return a pointer into memory + */ + template T cast(void){ + return boost::asio::buffer_cast(this->get()); + } + +private: + /*! + * Get a reference to the internal mutable buffer. + * The buffer has a reference to memory and a size. + * \return a boost asio mutable buffer + */ + virtual const boost::asio::mutable_buffer &get(void) = 0; +}; + +/*! + * A zero-copy interface for transport objects. + * Provides a way to get send and receive buffers + * with memory managed by the transport object. + */ +class UHD_API zero_copy_if : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Get a new receive buffer from this transport object. + */ + virtual managed_recv_buffer::sptr get_recv_buff(void) = 0; + + /*! + * Get a new send buffer from this transport object. + */ + virtual managed_send_buffer::sptr get_send_buff(void) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP */ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 1fc8ce14a..13fd50f65 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -25,39 +25,74 @@ using namespace uhd::transport; /*********************************************************************** - * Smart buffer implementation for udp zerocopy none - * - * This smart buffer implemention houses a const buffer. - * When the smart buffer is deleted, the buffer is freed. - * The memory in the const buffer is allocated with new [], - * and so the destructor frees the buffer with delete []. + * Managed receive buffer implementation for udp zero-copy asio: + * Frees the memory held by the const buffer on done. **********************************************************************/ -class smart_buffer_impl : public smart_buffer{ +class managed_recv_buffer_impl : public managed_recv_buffer{ public: - smart_buffer_impl(const boost::asio::const_buffer &buff){ - _buff = buff; + managed_recv_buffer_impl(const boost::asio::const_buffer &buff) : _buff(buff){ + _done = false; } - ~smart_buffer_impl(void){ + ~managed_recv_buffer_impl(void){ + if (not _done) this->done(); + } + + void done(void){ + _done = true; delete [] boost::asio::buffer_cast(_buff); } - const boost::asio::const_buffer &get(void) const{ +private: + const boost::asio::const_buffer &get(void){ return _buff; } + const boost::asio::const_buffer _buff; + bool _done; +}; + +/*********************************************************************** + * Managed send buffer implementation for udp zero-copy asio: + * Sends and frees the memory held by the mutable buffer on done. + **********************************************************************/ +class managed_send_buffer_impl : public managed_send_buffer{ +public: + managed_send_buffer_impl( + const boost::asio::mutable_buffer &buff, + boost::asio::ip::udp::socket *socket + ) : _buff(buff){ + _done = false; + _socket = socket; + } + + ~managed_send_buffer_impl(void){ + if (not _done) this->done(0); + } + + void done(size_t num_bytes){ + _done = true; + boost::uint32_t *mem = boost::asio::buffer_cast(_buff); + _socket->send(boost::asio::buffer(mem, num_bytes)); + delete [] mem; + } + private: - boost::asio::const_buffer _buff; + const boost::asio::mutable_buffer &get(void){ + return _buff; + } + + const boost::asio::mutable_buffer _buff; + boost::asio::ip::udp::socket *_socket; + bool _done; }; /*********************************************************************** - * UDP zero copy implementation class - * - * This is the portable zero copy implementation for systems - * where a faster, platform specific solution is not available. - * - * It uses boost asio udp sockets and the standard recv() class, - * and in-fact, is not actually doing a zero-copy implementation. + * Zero Copy UDP implementation with ASIO: + * This is the portable zero copy implementation for systems + * where a faster, platform specific solution is not available. + * However, it is not a true zero copy implementation as each + * send and recv requires a copy operation to/from userspace. **********************************************************************/ class udp_zero_copy_impl : public udp_zero_copy{ public: @@ -66,8 +101,8 @@ public: ~udp_zero_copy_impl(void); //send/recv - size_t send(const boost::asio::const_buffer &buff); - smart_buffer::sptr recv(void); + managed_recv_buffer::sptr get_recv_buff(void); + managed_send_buffer::sptr get_send_buff(void); private: boost::asio::ip::udp::socket *_socket; @@ -107,31 +142,33 @@ udp_zero_copy_impl::~udp_zero_copy_impl(void){ delete _socket; } -size_t udp_zero_copy_impl::send(const boost::asio::const_buffer &buff){ - return _socket->send(boost::asio::buffer(buff)); -} - -smart_buffer::sptr udp_zero_copy_impl::recv(void){ - size_t available = 0; +managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ + boost::uint32_t *buff_mem = new boost::uint32_t[1500/sizeof(boost::uint32_t)]; //implement timeout through polling and sleeping + size_t available = 0; boost::asio::deadline_timer timer(_socket->get_io_service()); timer.expires_from_now(boost::posix_time::milliseconds(100)); while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ boost::this_thread::sleep(boost::posix_time::milliseconds(1)); } - //allocate memory and create buffer - boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)]; - boost::asio::mutable_buffer buff(buff_mem, available); - //receive only if data is available if (available){ - _socket->receive(boost::asio::buffer(buff)); + available = _socket->receive(boost::asio::buffer(buff_mem, available)); } - //create a new smart buffer to house the data - return smart_buffer::sptr(new smart_buffer_impl(buff)); + //create a new managed buffer to house the data + return managed_recv_buffer::sptr( + new managed_recv_buffer_impl(boost::asio::buffer(buff_mem, available)) + ); +} + +managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){ + boost::uint32_t *buff_mem = new boost::uint32_t[1500/sizeof(boost::uint32_t)]; + return managed_send_buffer::sptr( + new managed_send_buffer_impl(boost::asio::buffer(buff_mem, 1500), _socket) + ); } size_t udp_zero_copy_impl::get_recv_buff_size(void){ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index a58e32619..a54c0a409 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -42,11 +42,13 @@ void usrp2_impl::io_init(void){ //send a small data packet so the usrp2 knows the udp source port //and the maximum number of lines (32 bit words) per packet + managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); boost::uint32_t data[2] = { htonl(USRP2_INVALID_VRT_HEADER), htonl(_max_rx_samples_per_packet) }; - _data_transport->send(asio::buffer(&data, sizeof(data))); + memcpy(send_buff->cast(), data, sizeof(data)); + send_buff->done(sizeof(data)); } #define unrolled_loop(__inst, __len){ \ @@ -127,15 +129,15 @@ static inline void usrp2_items_to_host_items( **********************************************************************/ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ //do a receive - _rx_smart_buff = _data_transport->recv(); + _rx_smart_buff = _data_transport->get_recv_buff(); //unpack the vrt header - size_t num_packet_words32 = asio::buffer_size(_rx_smart_buff->get())/sizeof(boost::uint32_t); + size_t num_packet_words32 = _rx_smart_buff->size()/sizeof(boost::uint32_t); if (num_packet_words32 == 0){ _rx_copy_buff = boost::asio::buffer("", 0); return; //must exit here after setting the buffer } - const boost::uint32_t *vrt_hdr = asio::buffer_cast(_rx_smart_buff->get()); + const boost::uint32_t *vrt_hdr = _rx_smart_buff->cast(); size_t num_header_words32_out, num_payload_words32_out, packet_count_out; try{ vrt::unpack( @@ -176,11 +178,12 @@ size_t usrp2_impl::send( ){ tx_metadata_t metadata = metadata_; //rw copy to change later - boost::uint32_t tx_mem[_mtu/sizeof(boost::uint32_t)]; + transport::managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); + boost::uint32_t *tx_mem = send_buff->cast(); size_t num_samps = std::min( - asio::buffer_size(buff)/io_type.size, - size_t(_max_tx_samples_per_packet) - ); + asio::buffer_size(buff), + send_buff->size() + )/io_type.size; //kill the end of burst flag if this is a fragment if (asio::buffer_size(buff)/io_type.size < num_samps) @@ -214,7 +217,7 @@ size_t usrp2_impl::send( } //send and return number of samples - _data_transport->send(asio::buffer(tx_mem, num_packet_words32*sizeof(boost::uint32_t))); + send_buff->done(num_packet_words32*sizeof(boost::uint32_t)); return num_samps; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index baa6530b8..be09c4ee1 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -136,7 +136,7 @@ private: (_mtu - _hdrs)/sizeof(boost::uint32_t) - uhd::transport::vrt::max_header_words32 ; - uhd::transport::smart_buffer::sptr _rx_smart_buff; + uhd::transport::managed_recv_buffer::sptr _rx_smart_buff; boost::asio::const_buffer _rx_copy_buff; size_t _fragment_offset_in_samps; void io_init(void); -- cgit v1.2.3 From e611e610f64b473cdd9d0aa5e40690d7550c3cc0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 13:39:09 -0700 Subject: Added data type conversion routines to transport api. --- host/include/uhd/transport/CMakeLists.txt | 1 + host/include/uhd/transport/convert_types.hpp | 59 +++++++++++ host/include/uhd/transport/vrt.hpp | 2 +- host/lib/CMakeLists.txt | 1 + host/lib/transport/convert_types.cpp | 144 +++++++++++++++++++++++++++ host/lib/transport/udp_zero_copy_asio.cpp | 11 +- host/lib/usrp/usrp2/io_impl.cpp | 128 ++++-------------------- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 + 8 files changed, 236 insertions(+), 112 deletions(-) create mode 100644 host/include/uhd/transport/convert_types.hpp create mode 100644 host/lib/transport/convert_types.cpp (limited to 'host/lib/transport') diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 9a94ead1b..4cefffa24 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -17,6 +17,7 @@ INSTALL(FILES + convert_types.hpp if_addrs.hpp udp_simple.hpp udp_zero_copy.hpp diff --git a/host/include/uhd/transport/convert_types.hpp b/host/include/uhd/transport/convert_types.hpp new file mode 100644 index 000000000..a4d999240 --- /dev/null +++ b/host/include/uhd/transport/convert_types.hpp @@ -0,0 +1,59 @@ +// +// Copyright 2010 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 . +// + +#ifndef INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP +#define INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP + +#include +#include +#include + +namespace uhd{ namespace transport{ + +/*! + * Convert IO samples to OWT samples. + * + * \param io_buff memory containing samples + * \param io_type the type of these samples + * \param otw_buff memory to write converted samples + * \param otw_type the type of these samples + * \param num_samps the number of samples in io_buff + */ +UHD_API void convert_io_type_to_otw_type( + const void *io_buff, const io_type_t &io_type, + void *otw_buff, const otw_type_t &otw_type, + size_t num_samps +); + +/*! + * Convert OTW samples to IO samples. + * + * \param otw_buff memory containing samples + * \param otw_type the type of these samples + * \param io_buff memory to write converted samples + * \param io_type the type of these samples + * \param num_samps the number of samples in io_buff + */ +UHD_API void convert_otw_type_to_io_type( + const void *otw_buff, const otw_type_t &otw_type, + void *io_buff, const io_type_t &io_type, + size_t num_samps +); + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP */ diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp index 04945b347..c30a73489 100644 --- a/host/include/uhd/transport/vrt.hpp +++ b/host/include/uhd/transport/vrt.hpp @@ -26,7 +26,7 @@ namespace uhd{ namespace transport{ namespace vrt{ - static const size_t max_header_words32 = 7; + static const size_t max_header_words32 = 5; //hdr+sid+tsi+tsf (no class id supported) /*! * Pack a vrt header from metadata. diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a5345cae4..fac1bd19f 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -24,6 +24,7 @@ SET(libuhd_sources load_modules.cpp types.cpp wax.cpp + transport/convert_types.cpp transport/if_addrs.cpp transport/udp_simple.cpp transport/vrt.cpp diff --git a/host/lib/transport/convert_types.cpp b/host/lib/transport/convert_types.cpp new file mode 100644 index 000000000..2a6854f50 --- /dev/null +++ b/host/lib/transport/convert_types.cpp @@ -0,0 +1,144 @@ +// +// Copyright 2010 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 . +// + +#include +#include +#include //endianness conversion +#include + +using namespace uhd; + +/*********************************************************************** + * Constants + **********************************************************************/ +typedef std::complex fc32_t; + +static const float shorts_per_float = float(1 << 15); +static const float floats_per_short = float(1.0/shorts_per_float); + +#define unrolled_loop(__inst, __len){ \ + size_t __i = 0; \ + for(; __i < (__len & ~0x3); __i+= 4){ \ + __inst(__i+0); __inst(__i+1); \ + __inst(__i+2); __inst(__i+3); \ + } \ + for(; __i < __len; __i++){ \ + __inst(__i); \ + } \ +} + +// set a boolean flag that indicates the endianess +#ifdef HAVE_BIG_ENDIAN +static const bool is_big_endian = true; +#else +static const bool is_big_endian = false; +#endif + +static inline void host_floats_to_usrp2_items( + boost::uint32_t *usrp2_items, + const fc32_t *host_floats, + size_t num_samps +){ + #define host_floats_to_usrp2_items_i(i){ \ + boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \ + boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \ + usrp2_items[i] = htonl((real << 16) | (imag << 0)); \ + } + unrolled_loop(host_floats_to_usrp2_items_i, num_samps); +} + +static inline void usrp2_items_to_host_floats( + fc32_t *host_floats, + const boost::uint32_t *usrp2_items, + size_t num_samps +){ + #define usrp2_items_to_host_floats_i(i){ \ + boost::uint32_t item = ntohl(usrp2_items[i]); \ + boost::int16_t real = boost::uint16_t(item >> 16); \ + boost::int16_t imag = boost::uint16_t(item >> 0); \ + host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \ + } + unrolled_loop(usrp2_items_to_host_floats_i, num_samps); +} + +static inline void host_items_to_usrp2_items( + boost::uint32_t *usrp2_items, + const boost::uint32_t *host_items, + size_t num_samps +){ + #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i]) + if (is_big_endian){ + std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t)); + } + else{ + unrolled_loop(host_items_to_usrp2_items_i, num_samps); + } +} + +static inline void usrp2_items_to_host_items( + boost::uint32_t *host_items, + const boost::uint32_t *usrp2_items, + size_t num_samps +){ + #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i]) + if (is_big_endian){ + std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t)); + } + else{ + unrolled_loop(usrp2_items_to_host_items_i, num_samps); + } +} + +void transport::convert_io_type_to_otw_type( + const void *io_buff, const io_type_t &io_type, + void *otw_buff, const otw_type_t &otw_type, + size_t num_samps +){ + //all we handle for now: + ASSERT_THROW(otw_type.width == 16 and otw_type.byteorder == otw_type_t::BO_BIG_ENDIAN); + + switch(io_type.tid){ + case io_type_t::COMPLEX_FLOAT32: + host_floats_to_usrp2_items((boost::uint32_t *)otw_buff, (const fc32_t*)io_buff, num_samps); + break; + case io_type_t::COMPLEX_INT16: + host_items_to_usrp2_items((boost::uint32_t *)otw_buff, (const boost::uint32_t*)io_buff, num_samps); + break; + default: + throw std::runtime_error(str(boost::format("convert_types: cannot handle type \"%c\"") % io_type.tid)); + } +} + +void transport::convert_otw_type_to_io_type( + const void *otw_buff, const otw_type_t &otw_type, + void *io_buff, const io_type_t &io_type, + size_t num_samps +){ + //all we handle for now: + ASSERT_THROW(otw_type.width == 16 and otw_type.byteorder == otw_type_t::BO_BIG_ENDIAN); + + switch(io_type.tid){ + case io_type_t::COMPLEX_FLOAT32: + usrp2_items_to_host_floats((fc32_t*)io_buff, (const boost::uint32_t *)otw_buff, num_samps); + break; + case io_type_t::COMPLEX_INT16: + usrp2_items_to_host_items((boost::uint32_t*)io_buff, (const boost::uint32_t *)otw_buff, num_samps); + break; + default: + throw std::runtime_error(str(boost::format("convert_types: cannot handle type \"%c\"") % io_type.tid)); + } +} diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 13fd50f65..3e0e80bd8 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -110,6 +110,9 @@ private: size_t get_recv_buff_size(void); void set_recv_buff_size(size_t); + + static const size_t _mtu = 1500; //FIXME we have no idea + static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp) }; udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ @@ -143,7 +146,7 @@ udp_zero_copy_impl::~udp_zero_copy_impl(void){ } managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ - boost::uint32_t *buff_mem = new boost::uint32_t[1500/sizeof(boost::uint32_t)]; + boost::uint32_t *buff_mem = new boost::uint32_t[_mtu/sizeof(boost::uint32_t)]; //implement timeout through polling and sleeping size_t available = 0; @@ -155,7 +158,7 @@ managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ //receive only if data is available if (available){ - available = _socket->receive(boost::asio::buffer(buff_mem, available)); + available = _socket->receive(boost::asio::buffer(buff_mem, _mtu)); } //create a new managed buffer to house the data @@ -165,9 +168,9 @@ managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ } managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){ - boost::uint32_t *buff_mem = new boost::uint32_t[1500/sizeof(boost::uint32_t)]; + boost::uint32_t *buff_mem = new boost::uint32_t[_mtu/sizeof(boost::uint32_t)]; return managed_send_buffer::sptr( - new managed_send_buffer_impl(boost::asio::buffer(buff_mem, 1500), _socket) + new managed_send_buffer_impl(boost::asio::buffer(buff_mem, _mtu-_hdrs), _socket) ); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index a54c0a409..19a1ecf0f 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -15,28 +15,25 @@ // along with this program. If not, see . // -#include -#include #include "usrp2_impl.hpp" +#include +#include +#include using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -/*********************************************************************** - * Constants - **********************************************************************/ -typedef std::complex fc32_t; -typedef std::complex sc16_t; - -static const float shorts_per_float = float(1 << 15); -static const float floats_per_short = float(1.0/shorts_per_float); - /*********************************************************************** * Helper Functions **********************************************************************/ void usrp2_impl::io_init(void){ + //setup otw type + _otw_type.width = 16; + _otw_type.shift = 0; + _otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; + //initially empty copy buffer _rx_copy_buff = asio::buffer("", 0); @@ -51,79 +48,6 @@ void usrp2_impl::io_init(void){ send_buff->done(sizeof(data)); } -#define unrolled_loop(__inst, __len){ \ - size_t __i = 0; \ - for(; __i < (__len & ~0x3); __i+= 4){ \ - __inst(__i+0); __inst(__i+1); \ - __inst(__i+2); __inst(__i+3); \ - } \ - for(; __i < __len; __i++){ \ - __inst(__i); \ - } \ -} - -// set a boolean flag that indicates the endianess -#ifdef HAVE_BIG_ENDIAN -static const bool is_big_endian = true; -#else -static const bool is_big_endian = false; -#endif - -static inline void host_floats_to_usrp2_items( - boost::uint32_t *usrp2_items, - const fc32_t *host_floats, - size_t num_samps -){ - #define host_floats_to_usrp2_items_i(i){ \ - boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \ - boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \ - usrp2_items[i] = htonl((real << 16) | (imag << 0)); \ - } - unrolled_loop(host_floats_to_usrp2_items_i, num_samps); -} - -static inline void usrp2_items_to_host_floats( - fc32_t *host_floats, - const boost::uint32_t *usrp2_items, - size_t num_samps -){ - #define usrp2_items_to_host_floats_i(i){ \ - boost::uint32_t item = ntohl(usrp2_items[i]); \ - boost::int16_t real = boost::uint16_t(item >> 16); \ - boost::int16_t imag = boost::uint16_t(item >> 0); \ - host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \ - } - unrolled_loop(usrp2_items_to_host_floats_i, num_samps); -} - -static inline void host_items_to_usrp2_items( - boost::uint32_t *usrp2_items, - const boost::uint32_t *host_items, - size_t num_samps -){ - #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i]) - if (is_big_endian){ - std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t)); - } - else{ - unrolled_loop(host_items_to_usrp2_items_i, num_samps); - } -} - -static inline void usrp2_items_to_host_items( - boost::uint32_t *host_items, - const boost::uint32_t *usrp2_items, - size_t num_samps -){ - #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i]) - if (is_big_endian){ - std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t)); - } - else{ - unrolled_loop(usrp2_items_to_host_items_i, num_samps); - } -} - /*********************************************************************** * Receive Raw Data **********************************************************************/ @@ -182,7 +106,7 @@ size_t usrp2_impl::send( boost::uint32_t *tx_mem = send_buff->cast(); size_t num_samps = std::min( asio::buffer_size(buff), - send_buff->size() + send_buff->size()-vrt::max_header_words32*sizeof(boost::uint32_t) )/io_type.size; //kill the end of burst flag if this is a fragment @@ -204,17 +128,12 @@ size_t usrp2_impl::send( boost::uint32_t *items = tx_mem + num_header_words32; //offset for data - //copy the samples into the send buffer - switch(io_type.tid){ - case io_type_t::COMPLEX_FLOAT32: - host_floats_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); - break; - case io_type_t::COMPLEX_INT16: - host_items_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); - break; - default: - throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%c\"") % io_type.tid)); - } + //copy-convert the samples into the send buffer + convert_io_type_to_otw_type( + asio::buffer_cast(buff), io_type, + (void*)items, _otw_type, + num_samps + ); //send and return number of samples send_buff->done(num_packet_words32*sizeof(boost::uint32_t)); @@ -254,17 +173,12 @@ size_t usrp2_impl::recv( metadata.fragment_offset = _fragment_offset_in_samps; _fragment_offset_in_samps += num_samps; //set for next time - //copy the samples from the recv buffer - switch(io_type.tid){ - case io_type_t::COMPLEX_FLOAT32: - usrp2_items_to_host_floats(asio::buffer_cast(buff), items, num_samps); - break; - case io_type_t::COMPLEX_INT16: - usrp2_items_to_host_items(asio::buffer_cast(buff), items, num_samps); - break; - default: - throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%c\"") % io_type.tid)); - } + //copy-convert the samples from the recv buffer + convert_otw_type_to_io_type( + (const void*)items, _otw_type, + asio::buffer_cast(buff), io_type, + num_samps + ); //update the rx copy buffer to reflect the bytes copied _rx_copy_buff = asio::buffer( diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index be09c4ee1..4e7154afa 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -139,6 +140,7 @@ private: uhd::transport::managed_recv_buffer::sptr _rx_smart_buff; boost::asio::const_buffer _rx_copy_buff; size_t _fragment_offset_in_samps; + uhd::otw_type_t _otw_type; void io_init(void); //udp transports for control and data -- cgit v1.2.3 From 24ca9fbd0784c7c53af6ad4f9035e8d43e888290 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 14:31:46 -0700 Subject: store the mtu and hdr len stuff only in the usrp2 impl --- host/lib/transport/udp_zero_copy_asio.cpp | 12 ++++-------- host/lib/usrp/usrp2/io_impl.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'host/lib/transport') diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 3e0e80bd8..7e643abad 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -110,9 +110,6 @@ private: size_t get_recv_buff_size(void); void set_recv_buff_size(size_t); - - static const size_t _mtu = 1500; //FIXME we have no idea - static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp) }; udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ @@ -146,8 +143,6 @@ udp_zero_copy_impl::~udp_zero_copy_impl(void){ } managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ - boost::uint32_t *buff_mem = new boost::uint32_t[_mtu/sizeof(boost::uint32_t)]; - //implement timeout through polling and sleeping size_t available = 0; boost::asio::deadline_timer timer(_socket->get_io_service()); @@ -157,8 +152,9 @@ managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ } //receive only if data is available + boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)]; if (available){ - available = _socket->receive(boost::asio::buffer(buff_mem, _mtu)); + available = _socket->receive(boost::asio::buffer(buff_mem, available)); } //create a new managed buffer to house the data @@ -168,9 +164,9 @@ managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ } managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){ - boost::uint32_t *buff_mem = new boost::uint32_t[_mtu/sizeof(boost::uint32_t)]; + boost::uint32_t *buff_mem = new boost::uint32_t[2000/sizeof(boost::uint32_t)]; return managed_send_buffer::sptr( - new managed_send_buffer_impl(boost::asio::buffer(buff_mem, _mtu-_hdrs), _socket) + new managed_send_buffer_impl(boost::asio::buffer(buff_mem, 2000), _socket) ); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 19a1ecf0f..62aca49ee 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -104,10 +104,11 @@ size_t usrp2_impl::send( transport::managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); boost::uint32_t *tx_mem = send_buff->cast(); - size_t num_samps = std::min( - asio::buffer_size(buff), - send_buff->size()-vrt::max_header_words32*sizeof(boost::uint32_t) - )/io_type.size; + size_t num_samps = std::min(std::min( + asio::buffer_size(buff)/io_type.size, + size_t(_max_tx_samples_per_packet)), + send_buff->size()/io_type.size + ); //kill the end of burst flag if this is a fragment if (asio::buffer_size(buff)/io_type.size < num_samps) -- cgit v1.2.3