Statistics
| Branch: | Tag: | Revision:

root / host / lib / transport / gen_convert_types.py @ 99494305

History | View | Annotate | Download (7 kB)

1
#!/usr/bin/env python
2
#
3
# Copyright 2010 Ettus Research LLC
4
#
5
# This program is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation, either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
#
18

    
19
TMPL_TEXT = """
20
#import time
21
/***********************************************************************
22
 * This file was generated by $file on $time.strftime("%c")
23
 **********************************************************************/
24

25
\#include <uhd/config.hpp>
26
\#include <uhd/transport/convert_types.hpp>
27
\#include <boost/cstdint.hpp>
28
\#include <boost/detail/endian.hpp>
29
\#include <stdexcept>
30
\#include "convert_types_impl.hpp"
31

32
using namespace uhd;
33

34
/***********************************************************************
35
 * Generate predicate for jump table
36
 **********************************************************************/
37
UHD_INLINE boost::uint8_t get_pred(
38
    const io_type_t &io_type,
39
    const otw_type_t &otw_type,
40
    size_t num_chans
41
){
42
    boost::uint8_t pred = 0;
43

44
    switch(otw_type.byteorder){
45
    \#ifdef BOOST_BIG_ENDIAN
46
    case otw_type_t::BO_BIG_ENDIAN:    pred |= $ph.nswap_p; break;
47
    case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.bswap_p; break;
48
    \#else
49
    case otw_type_t::BO_BIG_ENDIAN:    pred |= $ph.bswap_p; break;
50
    case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.nswap_p; break;
51
    \#endif
52
    case otw_type_t::BO_NATIVE:        pred |= $ph.nswap_p; break;
53
    default: throw std::runtime_error("unhandled otw byteorder type");
54
    }
55

56
    switch(otw_type.get_sample_size()){
57
    case sizeof(boost::uint32_t): pred |= $ph.item32_p; break;
58
    default: throw std::runtime_error("unhandled otw sample size");
59
    }
60

61
    switch(io_type.tid){
62
    case io_type_t::COMPLEX_FLOAT32: pred |= $ph.fc32_p; break;
63
    case io_type_t::COMPLEX_INT16:   pred |= $ph.sc16_p; break;
64
    default: throw std::runtime_error("unhandled io type id");
65
    }
66

67
    switch(num_chans){
68
    case 1: pred |= $ph.chan1_p; break;
69
    case 2: pred |= $ph.chan2_p; break;
70
    case 3: pred |= $ph.chan3_p; break;
71
    case 4: pred |= $ph.chan4_p; break;
72
    default: throw std::runtime_error("unhandled number of channels");
73
    }
74

75
    return pred;
76
}
77

78
/***********************************************************************
79
 * Convert host type to device type
80
 **********************************************************************/
81
void transport::convert_io_type_to_otw_type(
82
    const std::vector<const void *> &io_buffs,
83
    const io_type_t &io_type,
84
    void *otw_buff,
85
    const otw_type_t &otw_type,
86
    size_t nsamps_per_io_buff
87
){
88
    switch(get_pred(io_type, otw_type, io_buffs.size())){
89
    #for $pred in range(2**$ph.nbits)
90
    case $pred:
91
        #set $out_type = $ph.get_dev_type($pred)
92
        #set $in_type = $ph.get_host_type($pred)
93
        #set $num_chans = $ph.get_num_chans($pred)
94
        #set $converter = '_'.join([$in_type, 'to', $out_type])
95
        #if $num_chans == 1
96
        $(converter)_$ph.get_swap_type($pred)(
97
            reinterpret_cast<const $(in_type)_t *>(io_buffs.front()),
98
            reinterpret_cast<$(out_type)_t *>(otw_buff),
99
            nsamps_per_io_buff
100
        );
101
        #else
102
        for (size_t i = 0; i < nsamps_per_io_buff; i++){
103
            #for $j in range($num_chans)
104
            reinterpret_cast<$(out_type)_t *>(otw_buff)[i*$num_chans + $j] =
105
                #if $ph.get_swap_type($pred) == 'bswap'
106
                uhd::byteswap($(converter)(reinterpret_cast<const $(in_type)_t *>(io_buffs[$j])[i]));
107
                #else
108
                $(converter)(reinterpret_cast<const $(in_type)_t *>(io_buffs[$j])[i]);
109
                #end if
110
            #end for
111
        }
112
        #end if
113
        break;
114
    #end for
115
    }
116
}
117

118
/***********************************************************************
119
 * Convert device type to host type
120
 **********************************************************************/
121
void transport::convert_otw_type_to_io_type(
122
    const void *otw_buff,
123
    const otw_type_t &otw_type,
124
    std::vector<void *> &io_buffs,
125
    const io_type_t &io_type,
126
    size_t nsamps_per_io_buff
127
){
128
    switch(get_pred(io_type, otw_type, io_buffs.size())){
129
    #for $pred in range(2**$ph.nbits)
130
    case $pred:
131
        #set $out_type = $ph.get_host_type($pred)
132
        #set $in_type = $ph.get_dev_type($pred)
133
        #set $num_chans = $ph.get_num_chans($pred)
134
        #set $converter = '_'.join([$in_type, 'to', $out_type])
135
        #if $num_chans == 1
136
        $(converter)_$ph.get_swap_type($pred)(
137
            reinterpret_cast<const $(in_type)_t *>(otw_buff),
138
            reinterpret_cast<$(out_type)_t *>(io_buffs.front()),
139
            nsamps_per_io_buff
140
        );
141
        #else
142
        for (size_t i = 0; i < nsamps_per_io_buff; i++){
143
            #for $j in range($num_chans)
144
            reinterpret_cast<$(out_type)_t *>(io_buffs[$j])[i] =
145
                #if $ph.get_swap_type($pred) == 'bswap'
146
                $(converter)(uhd::byteswap(reinterpret_cast<const $(in_type)_t *>(otw_buff)[i*$num_chans + $j]));
147
                #else
148
                $(converter)(reinterpret_cast<const $(in_type)_t *>(otw_buff)[i*$num_chans + $j]);
149
                #end if
150
            #end for
151
        }
152
        #end if
153
        break;
154
    #end for
155
    }
156
}
157

158
"""
159

    
160
def parse_tmpl(_tmpl_text, **kwargs):
161
    from Cheetah.Template import Template
162
    return str(Template(_tmpl_text, kwargs))
163

    
164
class ph:
165
    bswap_p  = 0b00001
166
    nswap_p  = 0b00000
167
    item32_p = 0b00000
168
    sc16_p   = 0b00010
169
    fc32_p   = 0b00000
170
    chan1_p  = 0b00000
171
    chan2_p  = 0b00100
172
    chan3_p  = 0b01000
173
    chan4_p  = 0b01100
174

    
175
    nbits = 4 #see above
176

    
177
    @staticmethod
178
    def has(pred, mask, flag): return (pred & mask) == flag
179

    
180
    @staticmethod
181
    def get_swap_type(pred):
182
        mask = 0b1
183
        if ph.has(pred, mask, ph.bswap_p): return 'bswap'
184
        if ph.has(pred, mask, ph.nswap_p): return 'nswap'
185
        raise NotImplementedError
186

    
187
    @staticmethod
188
    def get_dev_type(pred):
189
        mask = 0b0
190
        if ph.has(pred, mask, ph.item32_p): return 'item32'
191
        raise NotImplementedError
192

    
193
    @staticmethod
194
    def get_host_type(pred):
195
        mask = 0b10
196
        if ph.has(pred, mask, ph.sc16_p): return 'sc16'
197
        if ph.has(pred, mask, ph.fc32_p): return 'fc32'
198
        raise NotImplementedError
199

    
200
    @staticmethod
201
    def get_num_chans(pred):
202
        mask = 0b1100
203
        if ph.has(pred, mask, ph.chan1_p): return 1
204
        if ph.has(pred, mask, ph.chan2_p): return 2
205
        if ph.has(pred, mask, ph.chan3_p): return 3
206
        if ph.has(pred, mask, ph.chan4_p): return 4
207
        raise NotImplementedError
208

    
209
if __name__ == '__main__':
210
    import sys
211
    open(sys.argv[1], 'w').write(parse_tmpl(TMPL_TEXT, file=__file__, ph=ph))