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.hpp | |
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.hpp')
-rw-r--r-- | host/lib/convert/convert_pack_sc12.hpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/host/lib/convert/convert_pack_sc12.hpp b/host/lib/convert/convert_pack_sc12.hpp new file mode 100644 index 000000000..754c47cd2 --- /dev/null +++ b/host/lib/convert/convert_pack_sc12.hpp @@ -0,0 +1,123 @@ +// +// 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 +// 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 <type_traits> +#include <uhd/utils/byteswap.hpp> +#include "convert_common.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> +void pack(item32_sc12_3x &output, int enable, const int32_t iq[8]) +{ + if (enable & CONVERT12_LINE0) + output.line0 = towire(iq[0] << 20 | iq[1] << 8 | iq[2] >> 4); + if (enable & CONVERT12_LINE1) + output.line1 = towire(iq[2] << 28 | iq[3] << 16 | iq[4] << 4 | iq[5] >> 8); + if (enable & CONVERT12_LINE2) + output.line2 = towire(iq[5] << 24 | iq[6] << 12 | iq[7] << 0); +} + +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 iq[8] { + int32_t(in0.real()*scalar) & 0xfff, + int32_t(in0.imag()*scalar) & 0xfff, + int32_t(in1.real()*scalar) & 0xfff, + int32_t(in1.imag()*scalar) & 0xfff, + + int32_t(in2.real()*scalar) & 0xfff, + int32_t(in2.imag()*scalar) & 0xfff, + int32_t(in3.real()*scalar) & 0xfff, + int32_t(in3.imag()*scalar) & 0xfff, + }; + pack<towire>(output, enable, iq); +} + +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 iq[8] { + int32_t(in0.real() >> 4) & 0xfff, + int32_t(in0.imag() >> 4) & 0xfff, + int32_t(in1.real() >> 4) & 0xfff, + int32_t(in1.imag() >> 4) & 0xfff, + + int32_t(in2.real() >> 4) & 0xfff, + int32_t(in2.imag() >> 4) & 0xfff, + int32_t(in3.real() >> 4) & 0xfff, + int32_t(in3.imag() >> 4) & 0xfff, + }; + pack<towire>(output, enable, iq); +} |