diff options
Diffstat (limited to 'host/lib/convert/gen_convert_impl.py')
-rw-r--r-- | host/lib/convert/gen_convert_impl.py | 186 |
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)) |