aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2015-09-01 16:00:31 -0700
committerMartin Braun <martin.braun@ettus.com>2015-09-01 16:00:31 -0700
commit71f6902d33f5c915bf15409428654ebfe7314226 (patch)
tree5afb9d6bfe517a951970c866da5f0bc857e073bd
parent6464a000150858b5d65a53490f0593d5ba1e4ca6 (diff)
downloaduhd-71f6902d33f5c915bf15409428654ebfe7314226.tar.gz
uhd-71f6902d33f5c915bf15409428654ebfe7314226.tar.bz2
uhd-71f6902d33f5c915bf15409428654ebfe7314226.zip
convert: Added s8, s16 types and did some refactoring
-rw-r--r--host/lib/convert/convert_item32.cpp3
-rw-r--r--host/lib/convert/gen_convert_general.py132
-rw-r--r--host/tests/convert_test.cpp163
3 files changed, 265 insertions, 33 deletions
diff --git a/host/lib/convert/convert_item32.cpp b/host/lib/convert/convert_item32.cpp
index 57bd64860..d52b47a1a 100644
--- a/host/lib/convert/convert_item32.cpp
+++ b/host/lib/convert/convert_item32.cpp
@@ -38,7 +38,10 @@
_DECLARE_ITEM32_CONVERTER(cpu_type, sc8) \
_DECLARE_ITEM32_CONVERTER(cpu_type, sc16)
+/* Create sc16<->sc16,sc8(otw) */
DECLARE_ITEM32_CONVERTER(sc16)
+/* Create fc32<->sc16,sc8(otw) */
DECLARE_ITEM32_CONVERTER(fc32)
+/* Create fc64<->sc16,sc8(otw) */
DECLARE_ITEM32_CONVERTER(fc64)
_DECLARE_ITEM32_CONVERTER(sc8, sc8)
diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py
index 4f9eeb747..ac8d7c7bd 100644
--- a/host/lib/convert/gen_convert_general.py
+++ b/host/lib/convert/gen_convert_general.py
@@ -39,30 +39,37 @@ DECLARE_CONVERTER(item32, 1, item32, 1, PRIORITY_GENERAL) {
}
"""
-TMPL_CONV_GEN2_ITEM32 = """
-DECLARE_CONVERTER(item32, 1, sc16_item32_{end}, 1, PRIORITY_GENERAL) {{
+# Some 32-bit types converters are also defined in convert_item32.cpp to
+# take care of quirks such as I/Q ordering on the wire etc.
+TMPL_CONV_ITEM32 = """
+DECLARE_CONVERTER({in_type}, 1, {out_type}, 1, PRIORITY_GENERAL) {{
const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
for (size_t i = 0; i < nsamps; i++) {{
- output[i] = {to_wire}(input[i]);
+ output[i] = {to_wire_or_host}(input[i]);
}}
}}
+"""
-DECLARE_CONVERTER(sc16_item32_{end}, 1, item32, 1, PRIORITY_GENERAL) {{
+# 64-bit data types are two consecutive item32 items
+TMPL_CONV_ITEM64 = """
+DECLARE_CONVERTER({in_type}, 1, {out_type}, 1, PRIORITY_GENERAL) {{
const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
- for (size_t i = 0; i < nsamps; i++) {{
- output[i] = {to_host}(input[i]);
+ // An item64 is two item32_t's
+ for (size_t i = 0; i < nsamps * 2; i++) {{
+ output[i] = {to_wire_or_host}(input[i]);
}}
}}
"""
-TMPL_CONV_U8 = """
-DECLARE_CONVERTER(u8, 1, u8_item32_{end}, 1, PRIORITY_GENERAL) {{
- const boost::uint32_t *input = reinterpret_cast<const boost::uint32_t *>(inputs[0]);
- boost::uint32_t *output = reinterpret_cast<boost::uint32_t *>(outputs[0]);
+
+TMPL_CONV_U8S8 = """
+DECLARE_CONVERTER({us8}, 1, {us8}_item32_{end}, 1, PRIORITY_GENERAL) {{
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
// 1) Copy all the 4-byte tuples
size_t n_words = nsamps / 4;
@@ -72,8 +79,8 @@ DECLARE_CONVERTER(u8, 1, u8_item32_{end}, 1, PRIORITY_GENERAL) {{
// 2) If nsamps was not a multiple of 4, copy the rest by hand
size_t bytes_left = nsamps % 4;
if (bytes_left) {{
- const u8_t *last_input_word = reinterpret_cast<const u8_t *>(&input[n_words]);
- u8_t *last_output_word = reinterpret_cast<u8_t *>(&output[n_words]);
+ const {us8}_t *last_input_word = reinterpret_cast<const {us8}_t *>(&input[n_words]);
+ {us8}_t *last_output_word = reinterpret_cast<{us8}_t *>(&output[n_words]);
for (size_t k = 0; k < bytes_left; k++) {{
last_output_word[k] = last_input_word[k];
}}
@@ -81,9 +88,9 @@ DECLARE_CONVERTER(u8, 1, u8_item32_{end}, 1, PRIORITY_GENERAL) {{
}}
}}
-DECLARE_CONVERTER(u8_item32_{end}, 1, u8, 1, PRIORITY_GENERAL) {{
- const boost::uint32_t *input = reinterpret_cast<const boost::uint32_t *>(inputs[0]);
- boost::uint32_t *output = reinterpret_cast<boost::uint32_t *>(outputs[0]);
+DECLARE_CONVERTER({us8}_item32_{end}, 1, {us8}, 1, PRIORITY_GENERAL) {{
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
// 1) Copy all the 4-byte tuples
size_t n_words = nsamps / 4;
@@ -93,9 +100,9 @@ DECLARE_CONVERTER(u8_item32_{end}, 1, u8, 1, PRIORITY_GENERAL) {{
// 2) If nsamps was not a multiple of 4, copy the rest by hand
size_t bytes_left = nsamps % 4;
if (bytes_left) {{
- boost::uint32_t last_input_word = {to_host}(input[n_words]);
- const u8_t *last_input_word_ptr = reinterpret_cast<const u8_t *>(&last_input_word);
- u8_t *last_output_word = reinterpret_cast<u8_t *>(&output[n_words]);
+ item32_t last_input_word = {to_host}(input[n_words]);
+ const {us8}_t *last_input_word_ptr = reinterpret_cast<const {us8}_t *>(&last_input_word);
+ {us8}_t *last_output_word = reinterpret_cast<{us8}_t *>(&output[n_words]);
for (size_t k = 0; k < bytes_left; k++) {{
last_output_word[k] = last_input_word_ptr[k];
}}
@@ -103,6 +110,44 @@ DECLARE_CONVERTER(u8_item32_{end}, 1, u8, 1, PRIORITY_GENERAL) {{
}}
"""
+TMPL_CONV_S16 = """
+DECLARE_CONVERTER(s16, 1, s16_item32_{end}, 1, PRIORITY_GENERAL) {{
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ // 1) Copy all the 4-byte tuples
+ size_t n_words = nsamps / 2;
+ for (size_t i = 0; i < n_words; i++) {{
+ output[i] = {to_wire}(input[i]);
+ }}
+ // 2) If nsamps was not a multiple of 2, copy the last one by hand
+ if (nsamps % 2) {{
+ const s16_t *last_input_word = reinterpret_cast<const s16_t *>(&input[n_words]);
+ s16_t *last_output_word = reinterpret_cast<s16_t *>(&output[n_words]);
+ last_output_word[0] = last_input_word[0];
+ output[n_words] = {to_wire}(output[n_words]);
+ }}
+}}
+
+DECLARE_CONVERTER(s16_item32_{end}, 1, s16, 1, PRIORITY_GENERAL) {{
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ // 1) Copy all the 4-byte tuples
+ size_t n_words = nsamps / 2;
+ for (size_t i = 0; i < n_words; i++) {{
+ output[i] = {to_host}(input[i]);
+ }}
+ // 2) If nsamps was not a multiple of 2, copy the last one by hand
+ if (nsamps % 2) {{
+ item32_t last_input_word = {to_host}(input[n_words]);
+ const s16_t *last_input_word_ptr = reinterpret_cast<const s16_t *>(&last_input_word);
+ s16_t *last_output_word = reinterpret_cast<s16_t *>(&output[n_words]);
+ last_output_word[0] = last_input_word_ptr[0];
+ }}
+}}
+"""
+
TMPL_CONV_USRP1_COMPLEX = """
DECLARE_CONVERTER(${cpu_type}, ${width}, sc16_item16_usrp1, 1, PRIORITY_GENERAL){
% for w in range(width):
@@ -164,23 +209,52 @@ if __name__ == '__main__':
file = os.path.basename(__file__)
output = parse_tmpl(TMPL_HEADER, file=file)
- #generate complex converters for all gen2 platforms
- for end, to_host, to_wire in (
- ('be', 'uhd::ntohx', 'uhd::htonx'),
- ('le', 'uhd::wtohx', 'uhd::htowx'),
- ):
- output += TMPL_CONV_GEN2_ITEM32.format(
- end=end, to_host=to_host, to_wire=to_wire
- )
- #generate raw (u8) converters:
+ ## Generate all data types that are exactly
+ ## item32 or multiples thereof:
+ for end in ('be', 'le'):
+ host_to_wire = {'be': 'uhd::htonx', 'le': 'uhd::htowx'}[end]
+ wire_to_host = {'be': 'uhd::ntohx', 'le': 'uhd::wtohx'}[end]
+ # item32 types (sc16->sc16 is a special case because it defaults
+ # to Q/I order on the wire:
+ for in_type, out_type, to_wire_or_host in (
+ ('item32', 'sc16_item32_{end}', host_to_wire),
+ ('sc16_item32_{end}', 'item32', wire_to_host),
+ ('f32', 'f32_item32_{end}', host_to_wire),
+ ('f32_item32_{end}', 'f32', wire_to_host),
+ ):
+ output += TMPL_CONV_ITEM32.format(
+ end=end, to_wire_or_host=to_wire_or_host,
+ in_type=in_type.format(end=end), out_type=out_type.format(end=end)
+ )
+ # 2xitem32 types:
+ for in_type, out_type in (
+ ('fc32', 'fc32_item32_{end}'),
+ ('fc32_item32_{end}', 'fc32'),
+ ):
+ output += TMPL_CONV_ITEM64.format(
+ end=end, to_wire_or_host=to_wire_or_host,
+ in_type=in_type.format(end=end), out_type=out_type.format(end=end)
+ )
+
+ ## Real 16-Bit:
for end, to_host, to_wire in (
('be', 'uhd::ntohx', 'uhd::htonx'),
('le', 'uhd::wtohx', 'uhd::htowx'),
):
- output += TMPL_CONV_U8.format(
- end=end, to_host=to_host, to_wire=to_wire
+ output += TMPL_CONV_S16.format(
+ end=end, to_host=to_host, to_wire=to_wire
)
+ ## Real 8-Bit Types:
+ for us8 in ('u8', 's8'):
+ for end, to_host, to_wire in (
+ ('be', 'uhd::ntohx', 'uhd::htonx'),
+ ('le', 'uhd::wtohx', 'uhd::htowx'),
+ ):
+ output += TMPL_CONV_U8S8.format(
+ us8=us8, end=end, to_host=to_host, to_wire=to_wire
+ )
+
#generate complex converters for usrp1 format (requires Cheetah)
for width in 1, 2, 4:
for cpu_type, do_scale in (
diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp
index d71d756dd..8d359d2e2 100644
--- a/host/tests/convert_test.cpp
+++ b/host/tests/convert_test.cpp
@@ -417,16 +417,16 @@ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_and_sc8){
}
/***********************************************************************
- * Test short conversion
+ * Test u8 conversion
**********************************************************************/
static void test_convert_types_u8(
size_t nsamps, convert::id_type &id
){
//fill the input samples
std::vector<boost::uint8_t> input(nsamps), output(nsamps);
- //BOOST_FOREACH(boost::uint8_t &in, input) in = boost::uint8_t(std::rand() & 0xFF);
- boost::uint32_t d = 48;
- BOOST_FOREACH(boost::uint8_t &in, input) in = d++;
+ BOOST_FOREACH(boost::uint8_t &in, input) in = boost::uint8_t(std::rand() & 0xFF);
+ //boost::uint32_t d = 48;
+ //BOOST_FOREACH(boost::uint8_t &in, input) in = d++;
//run the loopback and test
convert::id_type in_id = id;
@@ -455,3 +455,158 @@ BOOST_AUTO_TEST_CASE(test_convert_types_u8_and_u8){
test_convert_types_u8(nsamps, id);
}
}
+
+/***********************************************************************
+ * Test s8 conversion
+ **********************************************************************/
+static void test_convert_types_s8(
+ size_t nsamps, convert::id_type &id
+){
+ //fill the input samples
+ std::vector<boost::int8_t> input(nsamps), output(nsamps);
+ BOOST_FOREACH(boost::int8_t &in, input) in = boost::int8_t(std::rand() & 0xFF);
+
+ //run the loopback and test
+ convert::id_type in_id = id;
+ convert::id_type out_id = id;
+ std::swap(out_id.input_format, out_id.output_format);
+ std::swap(out_id.num_inputs, out_id.num_outputs);
+ loopback(nsamps, in_id, out_id, input, output);
+ BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_s8_and_s8){
+ convert::id_type id;
+ id.input_format = "s8";
+ id.num_inputs = 1;
+ id.num_outputs = 1;
+
+ //try various lengths to test edge cases
+ id.output_format = "s8_item32_le";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_s8(nsamps, id);
+ }
+
+ //try various lengths to test edge cases
+ id.output_format = "s8_item32_be";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_s8(nsamps, id);
+ }
+}
+
+/***********************************************************************
+ * Test s16 conversion
+ **********************************************************************/
+static void test_convert_types_s16(
+ size_t nsamps, convert::id_type &id
+){
+ //fill the input samples
+ std::vector<boost::int16_t> input(nsamps), output(nsamps);
+ BOOST_FOREACH(boost::int16_t &in, input) in = boost::int16_t(std::rand() & 0xFFFF);
+
+ //run the loopback and test
+ convert::id_type in_id = id;
+ convert::id_type out_id = id;
+ std::swap(out_id.input_format, out_id.output_format);
+ std::swap(out_id.num_inputs, out_id.num_outputs);
+ loopback(nsamps, in_id, out_id, input, output);
+ BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_s16_and_s16){
+ convert::id_type id;
+ id.input_format = "s16";
+ id.num_inputs = 1;
+ id.num_outputs = 1;
+
+ //try various lengths to test edge cases
+ id.output_format = "s16_item32_le";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_s16(nsamps, id);
+ }
+
+ //try various lengths to test edge cases
+ id.output_format = "s16_item32_be";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_s16(nsamps, id);
+ }
+}
+
+/***********************************************************************
+ * Test fc32 -> fc32 conversion
+ **********************************************************************/
+static void test_convert_types_fc32(
+ size_t nsamps, convert::id_type &id
+){
+ //fill the input samples
+ std::vector< std::complex<float> > input(nsamps), output(nsamps);
+ BOOST_FOREACH(fc32_t &in, input) in = fc32_t(
+ (std::rand()/float(RAND_MAX/2)) - 1,
+ (std::rand()/float(RAND_MAX/2)) - 1
+ );
+
+ //run the loopback and test
+ convert::id_type in_id = id;
+ convert::id_type out_id = id;
+ std::swap(out_id.input_format, out_id.output_format);
+ std::swap(out_id.num_inputs, out_id.num_outputs);
+ loopback(nsamps, in_id, out_id, input, output);
+ BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_fc32){
+ convert::id_type id;
+ id.input_format = "fc32";
+ id.num_inputs = 1;
+ id.num_outputs = 1;
+
+ //try various lengths to test edge cases
+ id.output_format = "fc32_item32_le";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_fc32(nsamps, id);
+ }
+
+ //try various lengths to test edge cases
+ id.output_format = "fc32_item32_be";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_fc32(nsamps, id);
+ }
+}
+
+/***********************************************************************
+ * Test f32 -> f32 conversion
+ **********************************************************************/
+static void test_convert_types_f32(
+ size_t nsamps, convert::id_type &id
+){
+ //fill the input samples
+ std::vector<float> input(nsamps), output(nsamps);
+ BOOST_FOREACH(float &in, input) in = float((std::rand()/float(RAND_MAX/2)) - 1);
+
+ //run the loopback and test
+ convert::id_type in_id = id;
+ convert::id_type out_id = id;
+ std::swap(out_id.input_format, out_id.output_format);
+ std::swap(out_id.num_inputs, out_id.num_outputs);
+ loopback(nsamps, in_id, out_id, input, output);
+ BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_f32_and_f32){
+ convert::id_type id;
+ id.input_format = "f32";
+ id.num_inputs = 1;
+ id.num_outputs = 1;
+
+ //try various lengths to test edge cases
+ id.output_format = "f32_item32_le";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_f32(nsamps, id);
+ }
+
+ //try various lengths to test edge cases
+ id.output_format = "f32_item32_be";
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_f32(nsamps, id);
+ }
+}