aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/convert/gen_convert_impl.py
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/convert/gen_convert_impl.py')
-rw-r--r--host/lib/convert/gen_convert_impl.py186
1 files changed, 186 insertions, 0 deletions
diff --git a/host/lib/convert/gen_convert_impl.py b/host/lib/convert/gen_convert_impl.py
new file mode 100644
index 000000000..71095ab97
--- /dev/null
+++ b/host/lib/convert/gen_convert_impl.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python
+#
+# Copyright 2010-2011 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/>.
+#
+
+TMPL_TEXT = """
+#import time
+/***********************************************************************
+ * This file was generated by $file on $time.strftime("%c")
+ **********************************************************************/
+typedef size_t pred_type;
+
+\#include <uhd/utils/algorithm.hpp>
+\#include <boost/lexical_cast.hpp>
+\#include <boost/detail/endian.hpp>
+\#include <stdexcept>
+
+enum dir_type{
+ DIR_OTW_TO_CPU = 0,
+ DIR_CPU_TO_OTW = 1
+};
+
+pred_type make_pred(const std::string &markup, dir_type &dir){
+ pred_type pred = 0;
+
+ try{
+ std::vector<std::string> tokens = std::split_string(markup, "_");
+ //token 0 is <convert>
+ std::string inp_type = tokens.at(1);
+ std::string num_inps = tokens.at(2);
+ //token 3 is <to>
+ std::string out_type = tokens.at(4);
+ std::string num_outs = tokens.at(5);
+ std::string swap_type = tokens.at(6);
+
+ std::string cpu_type, otw_type;
+ if (inp_type.find("item") == std::string::npos){
+ cpu_type = inp_type;
+ otw_type = out_type;
+ dir = DIR_CPU_TO_OTW;
+ }
+ else{
+ cpu_type = out_type;
+ otw_type = inp_type;
+ dir = DIR_OTW_TO_CPU;
+ }
+
+ if (cpu_type == "fc32") pred |= $ph.fc32_p;
+ else if (cpu_type == "sc16") pred |= $ph.sc16_p;
+ else throw std::runtime_error("unhandled io type " + cpu_type);
+
+ if (otw_type == "item32") pred |= $ph.item32_p;
+ else throw std::runtime_error("unhandled otw type " + otw_type);
+
+ int num_inputs = boost::lexical_cast<int>(num_inps);
+ int num_outputs = boost::lexical_cast<int>(num_outs);
+
+ switch(num_inputs*num_outputs){ //FIXME treated as one value
+ case 1: pred |= $ph.chan1_p; break;
+ case 2: pred |= $ph.chan2_p; break;
+ case 3: pred |= $ph.chan3_p; break;
+ case 4: pred |= $ph.chan4_p; break;
+ default: throw std::runtime_error("unhandled number of channels");
+ }
+
+ if (swap_type == "bswap") pred |= $ph.bswap_p;
+ else if (swap_type == "nswap") pred |= $ph.nswap_p;
+ else throw std::runtime_error("unhandled swap type");
+
+ }
+ catch(...){
+ throw std::runtime_error("convert::make_pred: could not parse markup: " + markup);
+ }
+
+ return pred;
+}
+
+UHD_INLINE pred_type make_pred(
+ const io_type_t &io_type,
+ const otw_type_t &otw_type,
+ size_t num_inputs,
+ size_t num_outputs
+){
+ pred_type pred = 0;
+
+ switch(otw_type.byteorder){
+ \#ifdef BOOST_BIG_ENDIAN
+ case otw_type_t::BO_BIG_ENDIAN: pred |= $ph.nswap_p; break;
+ case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.bswap_p; break;
+ \#else
+ case otw_type_t::BO_BIG_ENDIAN: pred |= $ph.bswap_p; break;
+ case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.nswap_p; break;
+ \#endif
+ case otw_type_t::BO_NATIVE: pred |= $ph.nswap_p; break;
+ default: throw std::runtime_error("unhandled otw byteorder type");
+ }
+
+ switch(otw_type.get_sample_size()){
+ case sizeof(boost::uint32_t): pred |= $ph.item32_p; break;
+ default: throw std::runtime_error("unhandled otw sample size");
+ }
+
+ switch(io_type.tid){
+ case io_type_t::COMPLEX_FLOAT32: pred |= $ph.fc32_p; break;
+ case io_type_t::COMPLEX_INT16: pred |= $ph.sc16_p; break;
+ default: throw std::runtime_error("unhandled io type id");
+ }
+
+ switch(num_inputs*num_outputs){ //FIXME treated as one value
+ case 1: pred |= $ph.chan1_p; break;
+ case 2: pred |= $ph.chan2_p; break;
+ case 3: pred |= $ph.chan3_p; break;
+ case 4: pred |= $ph.chan4_p; break;
+ default: throw std::runtime_error("unhandled number of channels");
+ }
+
+ return pred;
+}
+"""
+
+def parse_tmpl(_tmpl_text, **kwargs):
+ from Cheetah.Template import Template
+ return str(Template(_tmpl_text, kwargs))
+
+class ph:
+ bswap_p = 0b00001
+ nswap_p = 0b00000
+ item32_p = 0b00000
+ sc16_p = 0b00010
+ fc32_p = 0b00000
+ chan1_p = 0b00000
+ chan2_p = 0b00100
+ chan3_p = 0b01000
+ chan4_p = 0b01100
+
+ nbits = 4 #see above
+
+ @staticmethod
+ def has(pred, mask, flag): return (pred & mask) == flag
+
+ @staticmethod
+ def get_swap_type(pred):
+ mask = 0b1
+ if ph.has(pred, mask, ph.bswap_p): return 'bswap'
+ if ph.has(pred, mask, ph.nswap_p): return 'nswap'
+ raise NotImplementedError
+
+ @staticmethod
+ def get_dev_type(pred):
+ mask = 0b0
+ if ph.has(pred, mask, ph.item32_p): return 'item32'
+ raise NotImplementedError
+
+ @staticmethod
+ def get_host_type(pred):
+ mask = 0b10
+ if ph.has(pred, mask, ph.sc16_p): return 'sc16'
+ if ph.has(pred, mask, ph.fc32_p): return 'fc32'
+ raise NotImplementedError
+
+ @staticmethod
+ def get_num_chans(pred):
+ mask = 0b1100
+ if ph.has(pred, mask, ph.chan1_p): return 1
+ if ph.has(pred, mask, ph.chan2_p): return 2
+ if ph.has(pred, mask, ph.chan3_p): return 3
+ if ph.has(pred, mask, ph.chan4_p): return 4
+ raise NotImplementedError
+
+if __name__ == '__main__':
+ import sys, os
+ file = os.path.basename(__file__)
+ open(sys.argv[1], 'w').write(parse_tmpl(TMPL_TEXT, file=file, ph=ph))