convert.py revision 10427
1# Copyright (c) 2005 The Regents of The University of Michigan
2# Copyright (c) 2010 Advanced Micro Devices, Inc.
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28# Authors: Nathan Binkert
29#          Gabe Black
30
31# metric prefixes
32exa  = 1.0e18
33peta = 1.0e15
34tera = 1.0e12
35giga = 1.0e9
36mega = 1.0e6
37kilo = 1.0e3
38
39milli = 1.0e-3
40micro = 1.0e-6
41nano  = 1.0e-9
42pico  = 1.0e-12
43femto = 1.0e-15
44atto  = 1.0e-18
45
46# power of 2 prefixes
47kibi = 1024
48mebi = kibi * 1024
49gibi = mebi * 1024
50tebi = gibi * 1024
51pebi = tebi * 1024
52exbi = pebi * 1024
53
54# memory size configuration stuff
55def toFloat(value):
56    if not isinstance(value, str):
57        raise TypeError, "wrong type '%s' should be str" % type(value)
58
59    if value.endswith('Ei'):
60        return float(value[:-2]) * exbi
61    elif value.endswith('Pi'):
62        return float(value[:-2]) * pebi
63    elif value.endswith('Ti'):
64        return float(value[:-2]) * tebi
65    elif value.endswith('Gi'):
66        return float(value[:-2]) * gibi
67    elif value.endswith('Mi'):
68        return float(value[:-2]) * mebi
69    elif value.endswith('ki'):
70        return float(value[:-2]) * kibi
71    elif value.endswith('E'):
72        return float(value[:-1]) * exa
73    elif value.endswith('P'):
74        return float(value[:-1]) * peta
75    elif value.endswith('T'):
76        return float(value[:-1]) * tera
77    elif value.endswith('G'):
78        return float(value[:-1]) * giga
79    elif value.endswith('M'):
80        return float(value[:-1]) * mega
81    elif value.endswith('k'):
82        return float(value[:-1]) * kilo
83    elif value.endswith('m'):
84        return float(value[:-1]) * milli
85    elif value.endswith('u'):
86        return float(value[:-1]) * micro
87    elif value.endswith('n'):
88        return float(value[:-1]) * nano
89    elif value.endswith('p'):
90        return float(value[:-1]) * pico
91    elif value.endswith('f'):
92        return float(value[:-1]) * femto
93    else:
94        return float(value)
95
96def toInteger(value):
97    value = toFloat(value)
98    result = long(value)
99    if value != result:
100        raise ValueError, "cannot convert '%s' to integer" % value
101
102    return result
103
104_bool_dict = {
105    'true' : True,   't' : True,  'yes' : True, 'y' : True,  '1' : True,
106    'false' : False, 'f' : False, 'no' : False, 'n' : False, '0' : False
107    }
108
109def toBool(value):
110    if not isinstance(value, str):
111        raise TypeError, "wrong type '%s' should be str" % type(value)
112
113    value = value.lower()
114    result = _bool_dict.get(value, None)
115    if result == None:
116        raise ValueError, "cannot convert '%s' to bool" % value
117    return result
118
119def toFrequency(value):
120    if not isinstance(value, str):
121        raise TypeError, "wrong type '%s' should be str" % type(value)
122
123    if value.endswith('THz'):
124        return float(value[:-3]) * tera
125    elif value.endswith('GHz'):
126        return float(value[:-3]) * giga
127    elif value.endswith('MHz'):
128        return float(value[:-3]) * mega
129    elif value.endswith('kHz'):
130        return float(value[:-3]) * kilo
131    elif value.endswith('Hz'):
132        return float(value[:-2])
133
134    raise ValueError, "cannot convert '%s' to frequency" % value
135
136def toLatency(value):
137    if not isinstance(value, str):
138        raise TypeError, "wrong type '%s' should be str" % type(value)
139
140    if value.endswith('ps'):
141        return float(value[:-2]) * pico
142    elif value.endswith('ns'):
143        return float(value[:-2]) * nano
144    elif value.endswith('us'):
145        return float(value[:-2]) * micro
146    elif value.endswith('ms'):
147        return float(value[:-2]) * milli
148    elif value.endswith('s'):
149        return float(value[:-1])
150
151    raise ValueError, "cannot convert '%s' to latency" % value
152
153def anyToLatency(value):
154    """result is a clock period"""
155
156    if not isinstance(value, str):
157        raise TypeError, "wrong type '%s' should be str" % type(value)
158
159    try:
160        val = toFrequency(value)
161        if val != 0:
162            val = 1 / val
163        return val
164    except ValueError:
165        pass
166
167    try:
168        val = toLatency(value)
169        return val
170    except ValueError:
171        pass
172
173    raise ValueError, "cannot convert '%s' to clock period" % value
174
175def anyToFrequency(value):
176    """result is a clock period"""
177
178    if not isinstance(value, str):
179        raise TypeError, "wrong type '%s' should be str" % type(value)
180
181    try:
182        val = toFrequency(value)
183        return val
184    except ValueError:
185        pass
186
187    try:
188        val = toLatency(value)
189        if val != 0:
190            val = 1 / val
191        return val
192    except ValueError:
193        pass
194
195    raise ValueError, "cannot convert '%s' to clock period" % value
196
197def toNetworkBandwidth(value):
198    if not isinstance(value, str):
199        raise TypeError, "wrong type '%s' should be str" % type(value)
200
201    if value.endswith('Tbps'):
202        return float(value[:-4]) * tera
203    elif value.endswith('Gbps'):
204        return float(value[:-4]) * giga
205    elif value.endswith('Mbps'):
206        return float(value[:-4]) * mega
207    elif value.endswith('kbps'):
208        return float(value[:-4]) * kilo
209    elif value.endswith('bps'):
210        return float(value[:-3])
211    else:
212        return float(value)
213
214    raise ValueError, "cannot convert '%s' to network bandwidth" % value
215
216def toMemoryBandwidth(value):
217    if not isinstance(value, str):
218        raise TypeError, "wrong type '%s' should be str" % type(value)
219
220    if value.endswith('PB/s'):
221        return float(value[:-4]) * pebi
222    elif value.endswith('TB/s'):
223        return float(value[:-4]) * tebi
224    elif value.endswith('GB/s'):
225        return float(value[:-4]) * gibi
226    elif value.endswith('MB/s'):
227        return float(value[:-4]) * mebi
228    elif value.endswith('kB/s'):
229        return float(value[:-4]) * kibi
230    elif value.endswith('B/s'):
231        return float(value[:-3])
232
233    raise ValueError, "cannot convert '%s' to memory bandwidth" % value
234
235def toMemorySize(value):
236    if not isinstance(value, str):
237        raise TypeError, "wrong type '%s' should be str" % type(value)
238
239    if value.endswith('PB'):
240        return long(value[:-2]) * pebi
241    elif value.endswith('TB'):
242        return long(value[:-2]) * tebi
243    elif value.endswith('GB'):
244        return long(value[:-2]) * gibi
245    elif value.endswith('MB'):
246        return long(value[:-2]) * mebi
247    elif value.endswith('kB'):
248        return long(value[:-2]) * kibi
249    elif value.endswith('B'):
250        return long(value[:-1])
251
252    raise ValueError, "cannot convert '%s' to memory size" % value
253
254def toIpAddress(value):
255    if not isinstance(value, str):
256        raise TypeError, "wrong type '%s' should be str" % type(value)
257
258    bytes = value.split('.')
259    if len(bytes) != 4:
260        raise ValueError, 'invalid ip address %s' % value
261
262    for byte in bytes:
263        if not 0 <= int(byte) <= 0xff:
264            raise ValueError, 'invalid ip address %s' % value
265
266    return (int(bytes[0]) << 24) | (int(bytes[1]) << 16) | \
267           (int(bytes[2]) << 8)  | (int(bytes[3]) << 0)
268
269def toIpNetmask(value):
270    if not isinstance(value, str):
271        raise TypeError, "wrong type '%s' should be str" % type(value)
272
273    (ip, netmask) = value.split('/')
274    ip = toIpAddress(ip)
275    netmaskParts = netmask.split('.')
276    if len(netmaskParts) == 1:
277        if not 0 <= int(netmask) <= 32:
278            raise ValueError, 'invalid netmask %s' % netmask
279        return (ip, int(netmask))
280    elif len(netmaskParts) == 4:
281        netmaskNum = toIpAddress(netmask)
282        if netmaskNum == 0:
283            return (ip, 0)
284        testVal = 0
285        for i in range(32):
286            testVal |= (1 << (31 - i))
287            if testVal == netmaskNum:
288                return (ip, i + 1)
289        raise ValueError, 'invalid netmask %s' % netmask
290    else:
291        raise ValueError, 'invalid netmask %s' % netmask
292
293def toIpWithPort(value):
294    if not isinstance(value, str):
295        raise TypeError, "wrong type '%s' should be str" % type(value)
296
297    (ip, port) = value.split(':')
298    ip = toIpAddress(ip)
299    if not 0 <= int(port) <= 0xffff:
300        raise ValueError, 'invalid port %s' % port
301    return (ip, int(port))
302
303def toVoltage(value):
304    if not isinstance(value, str):
305        raise TypeError, "wrong type '%s' should be str" % type(value)
306
307    if value.endswith('mV'):
308        return float(value[:-2]) * milli
309    elif value.endswith('V'):
310        return float(value[:-1])
311
312    raise ValueError, "cannot convert '%s' to voltage" % value
313
314def toCurrent(value):
315    if not isinstance(value, str):
316        raise TypeError, "wrong type '%s' should be str" % type(value)
317
318    if value.endswith('A'):
319        return toFloat(value[:-1])
320
321    raise ValueError, "cannot convert '%s' to current" % value
322