util: Make dot_writer ignore NULL simobjects.
[gem5.git] / src / python / m5 / util / convert.py
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
32 exa = 1.0e18
33 peta = 1.0e15
34 tera = 1.0e12
35 giga = 1.0e9
36 mega = 1.0e6
37 kilo = 1.0e3
38
39 milli = 1.0e-3
40 micro = 1.0e-6
41 nano = 1.0e-9
42 pico = 1.0e-12
43 femto = 1.0e-15
44 atto = 1.0e-18
45
46 # power of 2 prefixes
47 kibi = 1024
48 mebi = kibi * 1024
49 gibi = mebi * 1024
50 tebi = gibi * 1024
51 pebi = tebi * 1024
52 exbi = pebi * 1024
53
54 # memory size configuration stuff
55 def 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
96 def 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
109 def 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
119 def 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
136 def 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
153 def 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
175 def 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
197 def 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
216 def 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
235 def 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
254 def 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
269 def 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
293 def 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
303 def 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
314 def 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