diff options
author | Tom Tsou <tom.tsou@ettus.com> | 2017-07-07 15:32:20 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-07-25 10:15:37 -0700 |
commit | 0e9f204029e5eac51d94f16ceb19f003e3faf7e8 (patch) | |
tree | ad71a66f4aa84fc17e965d8682741584f64aa18d /host/lib/convert/convert_pack_sc12.cpp | |
parent | 8223a289727bbda353bd7129512daf00d46d898c (diff) | |
download | uhd-0e9f204029e5eac51d94f16ceb19f003e3faf7e8.tar.gz uhd-0e9f204029e5eac51d94f16ceb19f003e3faf7e8.tar.bz2 uhd-0e9f204029e5eac51d94f16ceb19f003e3faf7e8.zip |
convert: Add SSE implementation for sc12
Implementation uses SSSE3 intructions to perform 12-bit
sample pack/unpack operations to/from standard 16 and 32
bit host values. Input/output shuffle orderings for a
single 128-bit SSE register with 16-bit integers shown
below.
16-bit interleaved I/Q
---------------------------------------
| Q3 | I3 | Q2 | I2 | Q1 | I1 | Q0 | I0 | Input
---------------------------------------
| 127 0 |
12-bit packed I/Q byteswapped
-----------------------
| I0 | Q0 | I1 | 0
|-----------------------|
| I1 | Q1 | I2 | Q2 | Output
|-----------------------|
| Q2 | I3 | Q3 |
|-----------------------|
| Unused | 3
-----------------------
31 0
Fixes: #1740, #966
Related: #1739
Diffstat (limited to 'host/lib/convert/convert_pack_sc12.cpp')
-rw-r--r-- | host/lib/convert/convert_pack_sc12.cpp | 116 |
1 files changed, 2 insertions, 114 deletions
diff --git a/host/lib/convert/convert_pack_sc12.cpp b/host/lib/convert/convert_pack_sc12.cpp index 2e45e19f5..85194dcdd 100644 --- a/host/lib/convert/convert_pack_sc12.cpp +++ b/host/lib/convert/convert_pack_sc12.cpp @@ -1,5 +1,5 @@ // -// Copyright 2013 Ettus Research LLC +// Copyright 2017 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 @@ -15,122 +15,10 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#include "convert_common.hpp" -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> -#include <boost/math/special_functions/round.hpp> -#include <vector> -#include <type_traits> +#include "convert_pack_sc12.hpp" using namespace uhd::convert; -typedef uint32_t (*towire32_type)(uint32_t); - -/* C language specification requires this to be packed - * (i.e., line0, line1, line2 will be in adjacent memory locations). - * If this was not true, we'd need compiler flags here to specify - * alignment/packing. - */ -struct item32_sc12_3x -{ - item32_t line0; - item32_t line1; - item32_t line2; -}; - -enum item32_sc12_3x_enable { - CONVERT12_LINE0 = 0x01, - CONVERT12_LINE1 = 0x02, - CONVERT12_LINE2 = 0x04, - CONVERT12_LINE_ALL = 0x07, -}; - -/* - * Packed 12-bit converter with selective line enable - * - * The converter operates on 4 complex inputs and selectively writes to one to - * three 32-bit lines. Line selection allows for partial writes of less than - * 4 complex samples, or a full 3 x 32-bit struct. Writes are always full 32-bit - * lines, so in the case of partial writes, the number of bytes written will - * exceed the the number of bytes filled by actual samples. - * - * _ _ _ _ _ _ _ _ - * |_ _ _1_ _ _|_ _| 0 - * |_2_ _ _|_ _ _3_| - * |_ _|_ _ _4_ _ _| 2 - * 31 0 - */ -template <towire32_type towire> -inline void pack(item32_sc12_3x &output, int enable, const int32_t i[4], const int32_t q[4]) -{ - if (enable & CONVERT12_LINE0) - output.line0 = towire(i[0] << 20 | q[0] << 8 | i[1] >> 4); - if (enable & CONVERT12_LINE1) - output.line1 = towire(i[1] << 28 | q[1] << 16 | i[2] << 4 | q[2] >> 8); - if (enable & CONVERT12_LINE2) - output.line2 = towire(q[2] << 24 | i[3] << 12 | q[3]); -} - -template <typename type, towire32_type towire> -void convert_star_4_to_sc12_item32_3 -( - const std::complex<type> &in0, - const std::complex<type> &in1, - const std::complex<type> &in2, - const std::complex<type> &in3, - const int enable, - item32_sc12_3x &output, - const double scalar, - typename std::enable_if<std::is_floating_point<type>::value>::type* = NULL -) -{ - int32_t i[4] { - int32_t(in0.real()*scalar) & 0xfff, - int32_t(in1.real()*scalar) & 0xfff, - int32_t(in2.real()*scalar) & 0xfff, - int32_t(in3.real()*scalar) & 0xfff, - }; - - int32_t q[4] { - int32_t(in0.imag()*scalar) & 0xfff, - int32_t(in1.imag()*scalar) & 0xfff, - int32_t(in2.imag()*scalar) & 0xfff, - int32_t(in3.imag()*scalar) & 0xfff, - }; - - pack<towire>(output, enable, i, q); -} - -template <typename type, towire32_type towire> -void convert_star_4_to_sc12_item32_3 -( - const std::complex<type> &in0, - const std::complex<type> &in1, - const std::complex<type> &in2, - const std::complex<type> &in3, - const int enable, - item32_sc12_3x &output, - const double, - typename std::enable_if<std::is_same<type, short>::value>::type* = NULL -) -{ - int32_t i[4] { - int32_t(in0.real() >> 4) & 0xfff, - int32_t(in1.real() >> 4) & 0xfff, - int32_t(in2.real() >> 4) & 0xfff, - int32_t(in3.real() >> 4) & 0xfff, - }; - - int32_t q[4] { - int32_t(in0.imag() >> 4) & 0xfff, - int32_t(in1.imag() >> 4) & 0xfff, - int32_t(in2.imag() >> 4) & 0xfff, - int32_t(in3.imag() >> 4) & 0xfff, - }; - - pack<towire>(output, enable, i, q); -} - template <typename type, towire32_type towire> struct convert_star_1_to_sc12_item32_1 : public converter { |