python: Remove unnecessary exports from pybind enums
[gem5.git] / src / python / m5 / params.py
1 # Copyright (c) 2012-2014, 2017-2019 ARM Limited
2 # All rights reserved.
3 #
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
12 #
13 # Copyright (c) 2004-2006 The Regents of The University of Michigan
14 # Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
15 # All rights reserved.
16 #
17 # Redistribution and use in source and binary forms, with or without
18 # modification, are permitted provided that the following conditions are
19 # met: redistributions of source code must retain the above copyright
20 # notice, this list of conditions and the following disclaimer;
21 # redistributions in binary form must reproduce the above copyright
22 # notice, this list of conditions and the following disclaimer in the
23 # documentation and/or other materials provided with the distribution;
24 # neither the name of the copyright holders nor the names of its
25 # contributors may be used to endorse or promote products derived from
26 # this software without specific prior written permission.
27 #
28 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
40 #####################################################################
41 #
42 # Parameter description classes
43 #
44 # The _params dictionary in each class maps parameter names to either
45 # a Param or a VectorParam object. These objects contain the
46 # parameter description string, the parameter type, and the default
47 # value (if any). The convert() method on these objects is used to
48 # force whatever value is assigned to the parameter to the appropriate
49 # type.
50 #
51 # Note that the default values are loaded into the class's attribute
52 # space when the parameter dictionary is initialized (in
53 # MetaSimObject._new_param()); after that point they aren't used.
54 #
55 #####################################################################
56
57 from __future__ import print_function
58 import six
59 if six.PY3:
60 long = int
61
62 import copy
63 import datetime
64 import re
65 import sys
66 import time
67 import math
68
69 from . import proxy
70 from . import ticks
71 from .util import *
72
73 def isSimObject(*args, **kwargs):
74 from . import SimObject
75 return SimObject.isSimObject(*args, **kwargs)
76
77 def isSimObjectSequence(*args, **kwargs):
78 from . import SimObject
79 return SimObject.isSimObjectSequence(*args, **kwargs)
80
81 def isSimObjectClass(*args, **kwargs):
82 from . import SimObject
83 return SimObject.isSimObjectClass(*args, **kwargs)
84
85 allParams = {}
86
87 class MetaParamValue(type):
88 def __new__(mcls, name, bases, dct):
89 cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
90 assert name not in allParams
91 allParams[name] = cls
92 return cls
93
94
95 # Dummy base class to identify types that are legitimate for SimObject
96 # parameters.
97 class ParamValue(object):
98 __metaclass__ = MetaParamValue
99 cmd_line_settable = False
100
101 # Generate the code needed as a prerequisite for declaring a C++
102 # object of this type. Typically generates one or more #include
103 # statements. Used when declaring parameters of this type.
104 @classmethod
105 def cxx_predecls(cls, code):
106 pass
107
108 @classmethod
109 def pybind_predecls(cls, code):
110 cls.cxx_predecls(code)
111
112 # default for printing to .ini file is regular string conversion.
113 # will be overridden in some cases
114 def ini_str(self):
115 return str(self)
116
117 # default for printing to .json file is regular string conversion.
118 # will be overridden in some cases, mostly to use native Python
119 # types where there are similar JSON types
120 def config_value(self):
121 return str(self)
122
123 # Prerequisites for .ini parsing with cxx_ini_parse
124 @classmethod
125 def cxx_ini_predecls(cls, code):
126 pass
127
128 # parse a .ini file entry for this param from string expression
129 # src into lvalue dest (of the param's C++ type)
130 @classmethod
131 def cxx_ini_parse(cls, code, src, dest, ret):
132 code('// Unhandled param type: %s' % cls.__name__)
133 code('%s false;' % ret)
134
135 # allows us to blithely call unproxy() on things without checking
136 # if they're really proxies or not
137 def unproxy(self, base):
138 return self
139
140 # Produce a human readable version of the stored value
141 def pretty_print(self, value):
142 return str(value)
143
144 # Regular parameter description.
145 class ParamDesc(object):
146 def __init__(self, ptype_str, ptype, *args, **kwargs):
147 self.ptype_str = ptype_str
148 # remember ptype only if it is provided
149 if ptype != None:
150 self.ptype = ptype
151
152 if args:
153 if len(args) == 1:
154 self.desc = args[0]
155 elif len(args) == 2:
156 self.default = args[0]
157 self.desc = args[1]
158 else:
159 raise TypeError('too many arguments')
160
161 if 'desc' in kwargs:
162 assert(not hasattr(self, 'desc'))
163 self.desc = kwargs['desc']
164 del kwargs['desc']
165
166 if 'default' in kwargs:
167 assert(not hasattr(self, 'default'))
168 self.default = kwargs['default']
169 del kwargs['default']
170
171 if kwargs:
172 raise TypeError('extra unknown kwargs %s' % kwargs)
173
174 if not hasattr(self, 'desc'):
175 raise TypeError('desc attribute missing')
176
177 def __getattr__(self, attr):
178 if attr == 'ptype':
179 from . import SimObject
180 ptype = SimObject.allClasses[self.ptype_str]
181 assert isSimObjectClass(ptype)
182 self.ptype = ptype
183 return ptype
184
185 raise AttributeError("'%s' object has no attribute '%s'" % \
186 (type(self).__name__, attr))
187
188 def example_str(self):
189 if hasattr(self.ptype, "ex_str"):
190 return self.ptype.ex_str
191 else:
192 return self.ptype_str
193
194 # Is the param available to be exposed on the command line
195 def isCmdLineSettable(self):
196 if hasattr(self.ptype, "cmd_line_settable"):
197 return self.ptype.cmd_line_settable
198 else:
199 return False
200
201 def convert(self, value):
202 if isinstance(value, proxy.BaseProxy):
203 value.set_param_desc(self)
204 return value
205 if 'ptype' not in self.__dict__ and isNullPointer(value):
206 # deferred evaluation of SimObject; continue to defer if
207 # we're just assigning a null pointer
208 return value
209 if isinstance(value, self.ptype):
210 return value
211 if isNullPointer(value) and isSimObjectClass(self.ptype):
212 return value
213 return self.ptype(value)
214
215 def pretty_print(self, value):
216 if isinstance(value, proxy.BaseProxy):
217 return str(value)
218 if isNullPointer(value):
219 return NULL
220 return self.ptype(value).pretty_print(value)
221
222 def cxx_predecls(self, code):
223 code('#include <cstddef>')
224 self.ptype.cxx_predecls(code)
225
226 def pybind_predecls(self, code):
227 self.ptype.pybind_predecls(code)
228
229 def cxx_decl(self, code):
230 code('${{self.ptype.cxx_type}} ${{self.name}};')
231
232 # Vector-valued parameter description. Just like ParamDesc, except
233 # that the value is a vector (list) of the specified type instead of a
234 # single value.
235
236 class VectorParamValue(list):
237 __metaclass__ = MetaParamValue
238 def __setattr__(self, attr, value):
239 raise AttributeError("Not allowed to set %s on '%s'" % \
240 (attr, type(self).__name__))
241
242 def config_value(self):
243 return [v.config_value() for v in self]
244
245 def ini_str(self):
246 return ' '.join([v.ini_str() for v in self])
247
248 def getValue(self):
249 return [ v.getValue() for v in self ]
250
251 def unproxy(self, base):
252 if len(self) == 1 and isinstance(self[0], proxy.BaseProxy):
253 # The value is a proxy (e.g. Parent.any, Parent.all or
254 # Parent.x) therefore try resolve it
255 return self[0].unproxy(base)
256 else:
257 return [v.unproxy(base) for v in self]
258
259 class SimObjectVector(VectorParamValue):
260 # support clone operation
261 def __call__(self, **kwargs):
262 return SimObjectVector([v(**kwargs) for v in self])
263
264 def clear_parent(self, old_parent):
265 for v in self:
266 v.clear_parent(old_parent)
267
268 def set_parent(self, parent, name):
269 if len(self) == 1:
270 self[0].set_parent(parent, name)
271 else:
272 width = int(math.ceil(math.log(len(self))/math.log(10)))
273 for i,v in enumerate(self):
274 v.set_parent(parent, "%s%0*d" % (name, width, i))
275
276 def has_parent(self):
277 return any([e.has_parent() for e in self if not isNullPointer(e)])
278
279 # return 'cpu0 cpu1' etc. for print_ini()
280 def get_name(self):
281 return ' '.join([v._name for v in self])
282
283 # By iterating through the constituent members of the vector here
284 # we can nicely handle iterating over all a SimObject's children
285 # without having to provide lots of special functions on
286 # SimObjectVector directly.
287 def descendants(self):
288 for v in self:
289 for obj in v.descendants():
290 yield obj
291
292 def get_config_as_dict(self):
293 a = []
294 for v in self:
295 a.append(v.get_config_as_dict())
296 return a
297
298 # If we are replacing an item in the vector, make sure to set the
299 # parent reference of the new SimObject to be the same as the parent
300 # of the SimObject being replaced. Useful to have if we created
301 # a SimObjectVector of temporary objects that will be modified later in
302 # configuration scripts.
303 def __setitem__(self, key, value):
304 val = self[key]
305 if value.has_parent():
306 warn("SimObject %s already has a parent" % value.get_name() +\
307 " that is being overwritten by a SimObjectVector")
308 value.set_parent(val.get_parent(), val._name)
309 super(SimObjectVector, self).__setitem__(key, value)
310
311 # Enumerate the params of each member of the SimObject vector. Creates
312 # strings that will allow indexing into the vector by the python code and
313 # allow it to be specified on the command line.
314 def enumerateParams(self, flags_dict = {},
315 cmd_line_str = "",
316 access_str = ""):
317 if hasattr(self, "_paramEnumed"):
318 print("Cycle detected enumerating params at %s?!" % (cmd_line_str))
319 else:
320 x = 0
321 for vals in self:
322 # Each entry in the SimObjectVector should be an
323 # instance of a SimObject
324 flags_dict = vals.enumerateParams(flags_dict,
325 cmd_line_str + "%d." % x,
326 access_str + "[%d]." % x)
327 x = x + 1
328
329 return flags_dict
330
331 class VectorParamDesc(ParamDesc):
332 # Convert assigned value to appropriate type. If the RHS is not a
333 # list or tuple, it generates a single-element list.
334 def convert(self, value):
335 if isinstance(value, (list, tuple)):
336 # list: coerce each element into new list
337 tmp_list = [ ParamDesc.convert(self, v) for v in value ]
338 elif isinstance(value, str):
339 # If input is a csv string
340 tmp_list = [ ParamDesc.convert(self, v) \
341 for v in value.strip('[').strip(']').split(',') ]
342 else:
343 # singleton: coerce to a single-element list
344 tmp_list = [ ParamDesc.convert(self, value) ]
345
346 if isSimObjectSequence(tmp_list):
347 return SimObjectVector(tmp_list)
348 else:
349 return VectorParamValue(tmp_list)
350
351 # Produce a human readable example string that describes
352 # how to set this vector parameter in the absence of a default
353 # value.
354 def example_str(self):
355 s = super(VectorParamDesc, self).example_str()
356 help_str = "[" + s + "," + s + ", ...]"
357 return help_str
358
359 # Produce a human readable representation of the value of this vector param.
360 def pretty_print(self, value):
361 if isinstance(value, (list, tuple)):
362 tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
363 elif isinstance(value, str):
364 tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
365 else:
366 tmp_list = [ ParamDesc.pretty_print(self, value) ]
367
368 return tmp_list
369
370 # This is a helper function for the new config system
371 def __call__(self, value):
372 if isinstance(value, (list, tuple)):
373 # list: coerce each element into new list
374 tmp_list = [ ParamDesc.convert(self, v) for v in value ]
375 elif isinstance(value, str):
376 # If input is a csv string
377 tmp_list = [ ParamDesc.convert(self, v) \
378 for v in value.strip('[').strip(']').split(',') ]
379 else:
380 # singleton: coerce to a single-element list
381 tmp_list = [ ParamDesc.convert(self, value) ]
382
383 return VectorParamValue(tmp_list)
384
385 def cxx_predecls(self, code):
386 code('#include <vector>')
387 self.ptype.cxx_predecls(code)
388
389 def pybind_predecls(self, code):
390 code('#include <vector>')
391 self.ptype.pybind_predecls(code)
392
393 def cxx_decl(self, code):
394 code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
395
396 class ParamFactory(object):
397 def __init__(self, param_desc_class, ptype_str = None):
398 self.param_desc_class = param_desc_class
399 self.ptype_str = ptype_str
400
401 def __getattr__(self, attr):
402 if self.ptype_str:
403 attr = self.ptype_str + '.' + attr
404 return ParamFactory(self.param_desc_class, attr)
405
406 # E.g., Param.Int(5, "number of widgets")
407 def __call__(self, *args, **kwargs):
408 ptype = None
409 try:
410 ptype = allParams[self.ptype_str]
411 except KeyError:
412 # if name isn't defined yet, assume it's a SimObject, and
413 # try to resolve it later
414 pass
415 return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
416
417 Param = ParamFactory(ParamDesc)
418 VectorParam = ParamFactory(VectorParamDesc)
419
420 #####################################################################
421 #
422 # Parameter Types
423 #
424 # Though native Python types could be used to specify parameter types
425 # (the 'ptype' field of the Param and VectorParam classes), it's more
426 # flexible to define our own set of types. This gives us more control
427 # over how Python expressions are converted to values (via the
428 # __init__() constructor) and how these values are printed out (via
429 # the __str__() conversion method).
430 #
431 #####################################################################
432
433 # String-valued parameter. Just mixin the ParamValue class with the
434 # built-in str class.
435 class String(ParamValue,str):
436 cxx_type = 'std::string'
437 cmd_line_settable = True
438
439 @classmethod
440 def cxx_predecls(self, code):
441 code('#include <string>')
442
443 def __call__(self, value):
444 self = value
445 return value
446
447 @classmethod
448 def cxx_ini_parse(self, code, src, dest, ret):
449 code('%s = %s;' % (dest, src))
450 code('%s true;' % ret)
451
452 def getValue(self):
453 return self
454
455 # superclass for "numeric" parameter values, to emulate math
456 # operations in a type-safe way. e.g., a Latency times an int returns
457 # a new Latency object.
458 class NumericParamValue(ParamValue):
459 @staticmethod
460 def unwrap(v):
461 return v.value if isinstance(v, NumericParamValue) else v
462
463 def __str__(self):
464 return str(self.value)
465
466 def __float__(self):
467 return float(self.value)
468
469 def __long__(self):
470 return long(self.value)
471
472 def __int__(self):
473 return int(self.value)
474
475 # hook for bounds checking
476 def _check(self):
477 return
478
479 def __mul__(self, other):
480 newobj = self.__class__(self)
481 newobj.value *= NumericParamValue.unwrap(other)
482 newobj._check()
483 return newobj
484
485 __rmul__ = __mul__
486
487 def __truediv__(self, other):
488 newobj = self.__class__(self)
489 newobj.value /= NumericParamValue.unwrap(other)
490 newobj._check()
491 return newobj
492
493 def __floordiv__(self, other):
494 newobj = self.__class__(self)
495 newobj.value //= NumericParamValue.unwrap(other)
496 newobj._check()
497 return newobj
498
499
500 def __add__(self, other):
501 newobj = self.__class__(self)
502 newobj.value += NumericParamValue.unwrap(other)
503 newobj._check()
504 return newobj
505
506 def __sub__(self, other):
507 newobj = self.__class__(self)
508 newobj.value -= NumericParamValue.unwrap(other)
509 newobj._check()
510 return newobj
511
512 def __iadd__(self, other):
513 self.value += NumericParamValue.unwrap(other)
514 self._check()
515 return self
516
517 def __isub__(self, other):
518 self.value -= NumericParamValue.unwrap(other)
519 self._check()
520 return self
521
522 def __imul__(self, other):
523 self.value *= NumericParamValue.unwrap(other)
524 self._check()
525 return self
526
527 def __itruediv__(self, other):
528 self.value /= NumericParamValue.unwrap(other)
529 self._check()
530 return self
531
532 def __ifloordiv__(self, other):
533 self.value //= NumericParamValue.unwrap(other)
534 self._check()
535 return self
536
537 def __lt__(self, other):
538 return self.value < NumericParamValue.unwrap(other)
539
540 # Python 2.7 pre __future__.division operators
541 # TODO: Remove these when after "import division from __future__"
542 __div__ = __truediv__
543 __idiv__ = __itruediv__
544
545 def config_value(self):
546 return self.value
547
548 @classmethod
549 def cxx_ini_predecls(cls, code):
550 # Assume that base/str.hh will be included anyway
551 # code('#include "base/str.hh"')
552 pass
553
554 # The default for parsing PODs from an .ini entry is to extract from an
555 # istringstream and let overloading choose the right type according to
556 # the dest type.
557 @classmethod
558 def cxx_ini_parse(self, code, src, dest, ret):
559 code('%s to_number(%s, %s);' % (ret, src, dest))
560
561 # Metaclass for bounds-checked integer parameters. See CheckedInt.
562 class CheckedIntType(MetaParamValue):
563 def __init__(cls, name, bases, dict):
564 super(CheckedIntType, cls).__init__(name, bases, dict)
565
566 # CheckedInt is an abstract base class, so we actually don't
567 # want to do any processing on it... the rest of this code is
568 # just for classes that derive from CheckedInt.
569 if name == 'CheckedInt':
570 return
571
572 if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
573 if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
574 panic("CheckedInt subclass %s must define either\n" \
575 " 'min' and 'max' or 'size' and 'unsigned'\n",
576 name);
577 if cls.unsigned:
578 cls.min = 0
579 cls.max = 2 ** cls.size - 1
580 else:
581 cls.min = -(2 ** (cls.size - 1))
582 cls.max = (2 ** (cls.size - 1)) - 1
583
584 # Abstract superclass for bounds-checked integer parameters. This
585 # class is subclassed to generate parameter classes with specific
586 # bounds. Initialization of the min and max bounds is done in the
587 # metaclass CheckedIntType.__init__.
588 class CheckedInt(NumericParamValue):
589 __metaclass__ = CheckedIntType
590 cmd_line_settable = True
591
592 def _check(self):
593 if not self.min <= self.value <= self.max:
594 raise TypeError('Integer param out of bounds %d < %d < %d' % \
595 (self.min, self.value, self.max))
596
597 def __init__(self, value):
598 if isinstance(value, str):
599 self.value = convert.toInteger(value)
600 elif isinstance(value, (int, long, float, NumericParamValue)):
601 self.value = long(value)
602 else:
603 raise TypeError("Can't convert object of type %s to CheckedInt" \
604 % type(value).__name__)
605 self._check()
606
607 def __call__(self, value):
608 self.__init__(value)
609 return value
610
611 def __index__(self):
612 return int(self.value)
613
614 @classmethod
615 def cxx_predecls(cls, code):
616 # most derived types require this, so we just do it here once
617 code('#include "base/types.hh"')
618
619 def getValue(self):
620 return long(self.value)
621
622 class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False
623 class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
624
625 class Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False
626 class UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True
627 class Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False
628 class UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True
629 class Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False
630 class UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True
631 class Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False
632 class UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True
633
634 class Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True
635 class Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True
636 class TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True
637 class UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True
638
639 class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100
640
641 class Cycles(CheckedInt):
642 cxx_type = 'Cycles'
643 size = 64
644 unsigned = True
645
646 def getValue(self):
647 from _m5.core import Cycles
648 return Cycles(self.value)
649
650 @classmethod
651 def cxx_ini_predecls(cls, code):
652 # Assume that base/str.hh will be included anyway
653 # code('#include "base/str.hh"')
654 pass
655
656 @classmethod
657 def cxx_ini_parse(cls, code, src, dest, ret):
658 code('uint64_t _temp;')
659 code('bool _ret = to_number(%s, _temp);' % src)
660 code('if (_ret)')
661 code(' %s = Cycles(_temp);' % dest)
662 code('%s _ret;' % ret)
663
664 class Float(ParamValue, float):
665 cxx_type = 'double'
666 cmd_line_settable = True
667
668 def __init__(self, value):
669 if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
670 self.value = float(value)
671 else:
672 raise TypeError("Can't convert object of type %s to Float" \
673 % type(value).__name__)
674
675 def __call__(self, value):
676 self.__init__(value)
677 return value
678
679 def getValue(self):
680 return float(self.value)
681
682 def config_value(self):
683 return self
684
685 @classmethod
686 def cxx_ini_predecls(cls, code):
687 code('#include <sstream>')
688
689 @classmethod
690 def cxx_ini_parse(self, code, src, dest, ret):
691 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
692
693 class MemorySize(CheckedInt):
694 cxx_type = 'uint64_t'
695 ex_str = '512MB'
696 size = 64
697 unsigned = True
698 def __init__(self, value):
699 if isinstance(value, MemorySize):
700 self.value = value.value
701 else:
702 self.value = convert.toMemorySize(value)
703 self._check()
704
705 class MemorySize32(CheckedInt):
706 cxx_type = 'uint32_t'
707 ex_str = '512MB'
708 size = 32
709 unsigned = True
710 def __init__(self, value):
711 if isinstance(value, MemorySize):
712 self.value = value.value
713 else:
714 self.value = convert.toMemorySize(value)
715 self._check()
716
717 class Addr(CheckedInt):
718 cxx_type = 'Addr'
719 size = 64
720 unsigned = True
721 def __init__(self, value):
722 if isinstance(value, Addr):
723 self.value = value.value
724 else:
725 try:
726 # Often addresses are referred to with sizes. Ex: A device
727 # base address is at "512MB". Use toMemorySize() to convert
728 # these into addresses. If the address is not specified with a
729 # "size", an exception will occur and numeric translation will
730 # proceed below.
731 self.value = convert.toMemorySize(value)
732 except (TypeError, ValueError):
733 # Convert number to string and use long() to do automatic
734 # base conversion (requires base=0 for auto-conversion)
735 self.value = long(str(value), base=0)
736
737 self._check()
738 def __add__(self, other):
739 if isinstance(other, Addr):
740 return self.value + other.value
741 else:
742 return self.value + other
743 def pretty_print(self, value):
744 try:
745 val = convert.toMemorySize(value)
746 except TypeError:
747 val = long(value)
748 return "0x%x" % long(val)
749
750 class AddrRange(ParamValue):
751 cxx_type = 'AddrRange'
752
753 def __init__(self, *args, **kwargs):
754 # Disable interleaving and hashing by default
755 self.intlvBits = 0
756 self.intlvMatch = 0
757 self.masks = []
758
759 def handle_kwargs(self, kwargs):
760 # An address range needs to have an upper limit, specified
761 # either explicitly with an end, or as an offset using the
762 # size keyword.
763 if 'end' in kwargs:
764 self.end = Addr(kwargs.pop('end'))
765 elif 'size' in kwargs:
766 self.end = self.start + Addr(kwargs.pop('size'))
767 else:
768 raise TypeError("Either end or size must be specified")
769
770 # Now on to the optional bit
771 if 'intlvMatch' in kwargs:
772 self.intlvMatch = int(kwargs.pop('intlvMatch'))
773
774 if 'masks' in kwargs:
775 self.masks = [ long(x) for x in list(kwargs.pop('masks')) ]
776 self.intlvBits = len(self.masks)
777 else:
778 if 'intlvBits' in kwargs:
779 self.intlvBits = int(kwargs.pop('intlvBits'))
780 self.masks = [0] * self.intlvBits
781 if 'intlvHighBit' not in kwargs:
782 raise TypeError("No interleave bits specified")
783 intlv_high_bit = int(kwargs.pop('intlvHighBit'))
784 xor_high_bit = 0
785 if 'xorHighBit' in kwargs:
786 xor_high_bit = int(kwargs.pop('xorHighBit'))
787 for i in range(0, self.intlvBits):
788 bit1 = intlv_high_bit - i
789 mask = 1 << bit1
790 if xor_high_bit != 0:
791 bit2 = xor_high_bit - i
792 mask |= 1 << bit2
793 self.masks[self.intlvBits - i - 1] = mask
794
795 if len(args) == 0:
796 self.start = Addr(kwargs.pop('start'))
797 handle_kwargs(self, kwargs)
798
799 elif len(args) == 1:
800 if kwargs:
801 self.start = Addr(args[0])
802 handle_kwargs(self, kwargs)
803 elif isinstance(args[0], (list, tuple)):
804 self.start = Addr(args[0][0])
805 self.end = Addr(args[0][1])
806 else:
807 self.start = Addr(0)
808 self.end = Addr(args[0])
809
810 elif len(args) == 2:
811 self.start = Addr(args[0])
812 self.end = Addr(args[1])
813 else:
814 raise TypeError("Too many arguments specified")
815
816 if kwargs:
817 raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
818
819 def __str__(self):
820 if len(self.masks) == 0:
821 return '%s:%s' % (self.start, self.end)
822 else:
823 return '%s:%s:%s:%s' % (self.start, self.end, self.intlvMatch,
824 ':'.join(str(m) for m in self.masks))
825
826 def size(self):
827 # Divide the size by the size of the interleaving slice
828 return (long(self.end) - long(self.start)) >> self.intlvBits
829
830 @classmethod
831 def cxx_predecls(cls, code):
832 Addr.cxx_predecls(code)
833 code('#include "base/addr_range.hh"')
834
835 @classmethod
836 def pybind_predecls(cls, code):
837 Addr.pybind_predecls(code)
838 code('#include "base/addr_range.hh"')
839
840 @classmethod
841 def cxx_ini_predecls(cls, code):
842 code('#include <sstream>')
843 code('#include <vector>')
844 code('#include "base/types.hh"')
845
846 @classmethod
847 def cxx_ini_parse(cls, code, src, dest, ret):
848 code('bool _ret = true;')
849 code('uint64_t _start, _end, _intlvMatch = 0;')
850 code('std::vector<Addr> _masks;')
851 code('char _sep;')
852 code('std::istringstream _stream(${src});')
853 code('_stream >> _start;')
854 code('_stream.get(_sep);')
855 code('_ret = _sep == \':\';')
856 code('_stream >> _end;')
857 code('if (!_stream.fail() && !_stream.eof()) {')
858 code(' _stream.get(_sep);')
859 code(' _ret = ret && _sep == \':\';')
860 code(' _stream >> _intlvMatch;')
861 code(' while (!_stream.fail() && !_stream.eof()) {')
862 code(' _stream.get(_sep);')
863 code(' _ret = ret && _sep == \':\';')
864 code(' Addr mask;')
865 code(' _stream >> mask;')
866 code(' _masks.push_back(mask);')
867 code(' }')
868 code('}')
869 code('_ret = _ret && !_stream.fail() && _stream.eof();')
870 code('if (_ret)')
871 code(' ${dest} = AddrRange(_start, _end, _masks, _intlvMatch);')
872 code('${ret} _ret;')
873
874 def getValue(self):
875 # Go from the Python class to the wrapped C++ class
876 from _m5.range import AddrRange
877
878 return AddrRange(long(self.start), long(self.end),
879 self.masks, int(self.intlvMatch))
880
881 # Boolean parameter type. Python doesn't let you subclass bool, since
882 # it doesn't want to let you create multiple instances of True and
883 # False. Thus this is a little more complicated than String.
884 class Bool(ParamValue):
885 cxx_type = 'bool'
886 cmd_line_settable = True
887
888 def __init__(self, value):
889 try:
890 self.value = convert.toBool(value)
891 except TypeError:
892 self.value = bool(value)
893
894 def __call__(self, value):
895 self.__init__(value)
896 return value
897
898 def getValue(self):
899 return bool(self.value)
900
901 def __str__(self):
902 return str(self.value)
903
904 # implement truth value testing for Bool parameters so that these params
905 # evaluate correctly during the python configuration phase
906 def __bool__(self):
907 return bool(self.value)
908
909 # Python 2.7 uses __nonzero__ instead of __bool__
910 __nonzero__ = __bool__
911
912 def ini_str(self):
913 if self.value:
914 return 'true'
915 return 'false'
916
917 def config_value(self):
918 return self.value
919
920 @classmethod
921 def cxx_ini_predecls(cls, code):
922 # Assume that base/str.hh will be included anyway
923 # code('#include "base/str.hh"')
924 pass
925
926 @classmethod
927 def cxx_ini_parse(cls, code, src, dest, ret):
928 code('%s to_bool(%s, %s);' % (ret, src, dest))
929
930 def IncEthernetAddr(addr, val = 1):
931 bytes = [ int(x, 16) for x in addr.split(':') ]
932 bytes[5] += val
933 for i in (5, 4, 3, 2, 1):
934 val,rem = divmod(bytes[i], 256)
935 bytes[i] = rem
936 if val == 0:
937 break
938 bytes[i - 1] += val
939 assert(bytes[0] <= 255)
940 return ':'.join(map(lambda x: '%02x' % x, bytes))
941
942 _NextEthernetAddr = "00:90:00:00:00:01"
943 def NextEthernetAddr():
944 global _NextEthernetAddr
945
946 value = _NextEthernetAddr
947 _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
948 return value
949
950 class EthernetAddr(ParamValue):
951 cxx_type = 'Net::EthAddr'
952 ex_str = "00:90:00:00:00:01"
953 cmd_line_settable = True
954
955 @classmethod
956 def cxx_predecls(cls, code):
957 code('#include "base/inet.hh"')
958
959 def __init__(self, value):
960 if value == NextEthernetAddr:
961 self.value = value
962 return
963
964 if not isinstance(value, str):
965 raise TypeError("expected an ethernet address and didn't get one")
966
967 bytes = value.split(':')
968 if len(bytes) != 6:
969 raise TypeError('invalid ethernet address %s' % value)
970
971 for byte in bytes:
972 if not 0 <= int(byte, base=16) <= 0xff:
973 raise TypeError('invalid ethernet address %s' % value)
974
975 self.value = value
976
977 def __call__(self, value):
978 self.__init__(value)
979 return value
980
981 def unproxy(self, base):
982 if self.value == NextEthernetAddr:
983 return EthernetAddr(self.value())
984 return self
985
986 def getValue(self):
987 from _m5.net import EthAddr
988 return EthAddr(self.value)
989
990 def __str__(self):
991 return self.value
992
993 def ini_str(self):
994 return self.value
995
996 @classmethod
997 def cxx_ini_parse(self, code, src, dest, ret):
998 code('%s = Net::EthAddr(%s);' % (dest, src))
999 code('%s true;' % ret)
1000
1001 # When initializing an IpAddress, pass in an existing IpAddress, a string of
1002 # the form "a.b.c.d", or an integer representing an IP.
1003 class IpAddress(ParamValue):
1004 cxx_type = 'Net::IpAddress'
1005 ex_str = "127.0.0.1"
1006 cmd_line_settable = True
1007
1008 @classmethod
1009 def cxx_predecls(cls, code):
1010 code('#include "base/inet.hh"')
1011
1012 def __init__(self, value):
1013 if isinstance(value, IpAddress):
1014 self.ip = value.ip
1015 else:
1016 try:
1017 self.ip = convert.toIpAddress(value)
1018 except TypeError:
1019 self.ip = long(value)
1020 self.verifyIp()
1021
1022 def __call__(self, value):
1023 self.__init__(value)
1024 return value
1025
1026 def __str__(self):
1027 tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)]
1028 return '%d.%d.%d.%d' % tuple(tup)
1029
1030 def __eq__(self, other):
1031 if isinstance(other, IpAddress):
1032 return self.ip == other.ip
1033 elif isinstance(other, str):
1034 try:
1035 return self.ip == convert.toIpAddress(other)
1036 except:
1037 return False
1038 else:
1039 return self.ip == other
1040
1041 def __ne__(self, other):
1042 return not (self == other)
1043
1044 def verifyIp(self):
1045 if self.ip < 0 or self.ip >= (1 << 32):
1046 raise TypeError("invalid ip address %#08x" % self.ip)
1047
1048 def getValue(self):
1049 from _m5.net import IpAddress
1050 return IpAddress(self.ip)
1051
1052 # When initializing an IpNetmask, pass in an existing IpNetmask, a string of
1053 # the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as
1054 # positional or keyword arguments.
1055 class IpNetmask(IpAddress):
1056 cxx_type = 'Net::IpNetmask'
1057 ex_str = "127.0.0.0/24"
1058 cmd_line_settable = True
1059
1060 @classmethod
1061 def cxx_predecls(cls, code):
1062 code('#include "base/inet.hh"')
1063
1064 def __init__(self, *args, **kwargs):
1065 def handle_kwarg(self, kwargs, key, elseVal = None):
1066 if key in kwargs:
1067 setattr(self, key, kwargs.pop(key))
1068 elif elseVal:
1069 setattr(self, key, elseVal)
1070 else:
1071 raise TypeError("No value set for %s" % key)
1072
1073 if len(args) == 0:
1074 handle_kwarg(self, kwargs, 'ip')
1075 handle_kwarg(self, kwargs, 'netmask')
1076
1077 elif len(args) == 1:
1078 if kwargs:
1079 if not 'ip' in kwargs and not 'netmask' in kwargs:
1080 raise TypeError("Invalid arguments")
1081 handle_kwarg(self, kwargs, 'ip', args[0])
1082 handle_kwarg(self, kwargs, 'netmask', args[0])
1083 elif isinstance(args[0], IpNetmask):
1084 self.ip = args[0].ip
1085 self.netmask = args[0].netmask
1086 else:
1087 (self.ip, self.netmask) = convert.toIpNetmask(args[0])
1088
1089 elif len(args) == 2:
1090 self.ip = args[0]
1091 self.netmask = args[1]
1092 else:
1093 raise TypeError("Too many arguments specified")
1094
1095 if kwargs:
1096 raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
1097
1098 self.verify()
1099
1100 def __call__(self, value):
1101 self.__init__(value)
1102 return value
1103
1104 def __str__(self):
1105 return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
1106
1107 def __eq__(self, other):
1108 if isinstance(other, IpNetmask):
1109 return self.ip == other.ip and self.netmask == other.netmask
1110 elif isinstance(other, str):
1111 try:
1112 return (self.ip, self.netmask) == convert.toIpNetmask(other)
1113 except:
1114 return False
1115 else:
1116 return False
1117
1118 def verify(self):
1119 self.verifyIp()
1120 if self.netmask < 0 or self.netmask > 32:
1121 raise TypeError("invalid netmask %d" % netmask)
1122
1123 def getValue(self):
1124 from _m5.net import IpNetmask
1125 return IpNetmask(self.ip, self.netmask)
1126
1127 # When initializing an IpWithPort, pass in an existing IpWithPort, a string of
1128 # the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
1129 class IpWithPort(IpAddress):
1130 cxx_type = 'Net::IpWithPort'
1131 ex_str = "127.0.0.1:80"
1132 cmd_line_settable = True
1133
1134 @classmethod
1135 def cxx_predecls(cls, code):
1136 code('#include "base/inet.hh"')
1137
1138 def __init__(self, *args, **kwargs):
1139 def handle_kwarg(self, kwargs, key, elseVal = None):
1140 if key in kwargs:
1141 setattr(self, key, kwargs.pop(key))
1142 elif elseVal:
1143 setattr(self, key, elseVal)
1144 else:
1145 raise TypeError("No value set for %s" % key)
1146
1147 if len(args) == 0:
1148 handle_kwarg(self, kwargs, 'ip')
1149 handle_kwarg(self, kwargs, 'port')
1150
1151 elif len(args) == 1:
1152 if kwargs:
1153 if not 'ip' in kwargs and not 'port' in kwargs:
1154 raise TypeError("Invalid arguments")
1155 handle_kwarg(self, kwargs, 'ip', args[0])
1156 handle_kwarg(self, kwargs, 'port', args[0])
1157 elif isinstance(args[0], IpWithPort):
1158 self.ip = args[0].ip
1159 self.port = args[0].port
1160 else:
1161 (self.ip, self.port) = convert.toIpWithPort(args[0])
1162
1163 elif len(args) == 2:
1164 self.ip = args[0]
1165 self.port = args[1]
1166 else:
1167 raise TypeError("Too many arguments specified")
1168
1169 if kwargs:
1170 raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
1171
1172 self.verify()
1173
1174 def __call__(self, value):
1175 self.__init__(value)
1176 return value
1177
1178 def __str__(self):
1179 return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
1180
1181 def __eq__(self, other):
1182 if isinstance(other, IpWithPort):
1183 return self.ip == other.ip and self.port == other.port
1184 elif isinstance(other, str):
1185 try:
1186 return (self.ip, self.port) == convert.toIpWithPort(other)
1187 except:
1188 return False
1189 else:
1190 return False
1191
1192 def verify(self):
1193 self.verifyIp()
1194 if self.port < 0 or self.port > 0xffff:
1195 raise TypeError("invalid port %d" % self.port)
1196
1197 def getValue(self):
1198 from _m5.net import IpWithPort
1199 return IpWithPort(self.ip, self.port)
1200
1201 time_formats = [ "%a %b %d %H:%M:%S %Z %Y",
1202 "%a %b %d %H:%M:%S %Y",
1203 "%Y/%m/%d %H:%M:%S",
1204 "%Y/%m/%d %H:%M",
1205 "%Y/%m/%d",
1206 "%m/%d/%Y %H:%M:%S",
1207 "%m/%d/%Y %H:%M",
1208 "%m/%d/%Y",
1209 "%m/%d/%y %H:%M:%S",
1210 "%m/%d/%y %H:%M",
1211 "%m/%d/%y"]
1212
1213
1214 def parse_time(value):
1215 from time import gmtime, strptime, struct_time, time
1216 from datetime import datetime, date
1217
1218 if isinstance(value, struct_time):
1219 return value
1220
1221 if isinstance(value, (int, long)):
1222 return gmtime(value)
1223
1224 if isinstance(value, (datetime, date)):
1225 return value.timetuple()
1226
1227 if isinstance(value, str):
1228 if value in ('Now', 'Today'):
1229 return time.gmtime(time.time())
1230
1231 for format in time_formats:
1232 try:
1233 return strptime(value, format)
1234 except ValueError:
1235 pass
1236
1237 raise ValueError("Could not parse '%s' as a time" % value)
1238
1239 class Time(ParamValue):
1240 cxx_type = 'tm'
1241
1242 @classmethod
1243 def cxx_predecls(cls, code):
1244 code('#include <time.h>')
1245
1246 def __init__(self, value):
1247 self.value = parse_time(value)
1248
1249 def __call__(self, value):
1250 self.__init__(value)
1251 return value
1252
1253 def getValue(self):
1254 from _m5.core import tm
1255 import calendar
1256
1257 return tm.gmtime(calendar.timegm(self.value))
1258
1259 def __str__(self):
1260 return time.asctime(self.value)
1261
1262 def ini_str(self):
1263 return str(self)
1264
1265 def get_config_as_dict(self):
1266 assert false
1267 return str(self)
1268
1269 @classmethod
1270 def cxx_ini_predecls(cls, code):
1271 code('#include <time.h>')
1272
1273 @classmethod
1274 def cxx_ini_parse(cls, code, src, dest, ret):
1275 code('char *_parse_ret = strptime((${src}).c_str(),')
1276 code(' "%a %b %d %H:%M:%S %Y", &(${dest}));')
1277 code('${ret} _parse_ret && *_parse_ret == \'\\0\';');
1278
1279 # Enumerated types are a little more complex. The user specifies the
1280 # type as Enum(foo) where foo is either a list or dictionary of
1281 # alternatives (typically strings, but not necessarily so). (In the
1282 # long run, the integer value of the parameter will be the list index
1283 # or the corresponding dictionary value. For now, since we only check
1284 # that the alternative is valid and then spit it into a .ini file,
1285 # there's not much point in using the dictionary.)
1286
1287 # What Enum() must do is generate a new type encapsulating the
1288 # provided list/dictionary so that specific values of the parameter
1289 # can be instances of that type. We define two hidden internal
1290 # classes (_ListEnum and _DictEnum) to serve as base classes, then
1291 # derive the new type from the appropriate base class on the fly.
1292
1293 allEnums = {}
1294 # Metaclass for Enum types
1295 class MetaEnum(MetaParamValue):
1296 def __new__(mcls, name, bases, dict):
1297 assert name not in allEnums
1298
1299 cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
1300 allEnums[name] = cls
1301 return cls
1302
1303 def __init__(cls, name, bases, init_dict):
1304 if 'map' in init_dict:
1305 if not isinstance(cls.map, dict):
1306 raise TypeError("Enum-derived class attribute 'map' " \
1307 "must be of type dict")
1308 # build list of value strings from map
1309 cls.vals = list(cls.map.keys())
1310 cls.vals.sort()
1311 elif 'vals' in init_dict:
1312 if not isinstance(cls.vals, list):
1313 raise TypeError("Enum-derived class attribute 'vals' " \
1314 "must be of type list")
1315 # build string->value map from vals sequence
1316 cls.map = {}
1317 for idx,val in enumerate(cls.vals):
1318 cls.map[val] = idx
1319 else:
1320 raise TypeError("Enum-derived class must define "\
1321 "attribute 'map' or 'vals'")
1322
1323 if cls.is_class:
1324 cls.cxx_type = '%s' % name
1325 else:
1326 cls.cxx_type = 'Enums::%s' % name
1327
1328 super(MetaEnum, cls).__init__(name, bases, init_dict)
1329
1330 # Generate C++ class declaration for this enum type.
1331 # Note that we wrap the enum in a class/struct to act as a namespace,
1332 # so that the enum strings can be brief w/o worrying about collisions.
1333 def cxx_decl(cls, code):
1334 wrapper_name = cls.wrapper_name
1335 wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
1336 name = cls.__name__ if cls.enum_name is None else cls.enum_name
1337 idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
1338
1339 code('''\
1340 #ifndef $idem_macro
1341 #define $idem_macro
1342
1343 ''')
1344 if cls.is_class:
1345 code('''\
1346 enum class $name {
1347 ''')
1348 else:
1349 code('''\
1350 $wrapper $wrapper_name {
1351 enum $name {
1352 ''')
1353 code.indent(1)
1354 code.indent(1)
1355 for val in cls.vals:
1356 code('$val = ${{cls.map[val]}},')
1357 code('Num_$name = ${{len(cls.vals)}}')
1358 code.dedent(1)
1359 code('};')
1360
1361 if cls.is_class:
1362 code('''\
1363 extern const char *${name}Strings[static_cast<int>(${name}::Num_${name})];
1364 ''')
1365 elif cls.wrapper_is_struct:
1366 code('static const char *${name}Strings[Num_${name}];')
1367 else:
1368 code('extern const char *${name}Strings[Num_${name}];')
1369
1370 if not cls.is_class:
1371 code.dedent(1)
1372 code('};')
1373
1374 code()
1375 code('#endif // $idem_macro')
1376
1377 def cxx_def(cls, code):
1378 wrapper_name = cls.wrapper_name
1379 file_name = cls.__name__
1380 name = cls.__name__ if cls.enum_name is None else cls.enum_name
1381
1382 code('#include "enums/$file_name.hh"')
1383 if cls.wrapper_is_struct:
1384 code('const char *${wrapper_name}::${name}Strings'
1385 '[Num_${name}] =')
1386 else:
1387 if cls.is_class:
1388 code('''\
1389 const char *${name}Strings[static_cast<int>(${name}::Num_${name})] =
1390 ''')
1391 else:
1392 code('namespace Enums {')
1393 code.indent(1)
1394 code('const char *${name}Strings[Num_${name}] =')
1395
1396 code('{')
1397 code.indent(1)
1398 for val in cls.vals:
1399 code('"$val",')
1400 code.dedent(1)
1401 code('};')
1402
1403 if not cls.wrapper_is_struct and not cls.is_class:
1404 code.dedent(1)
1405 code('} // namespace $wrapper_name')
1406
1407
1408 def pybind_def(cls, code):
1409 name = cls.__name__
1410 enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name
1411 wrapper_name = enum_name if cls.is_class else cls.wrapper_name
1412
1413 code('''#include "pybind11/pybind11.h"
1414 #include "pybind11/stl.h"
1415
1416 #include <sim/init.hh>
1417
1418 namespace py = pybind11;
1419
1420 static void
1421 module_init(py::module &m_internal)
1422 {
1423 py::module m = m_internal.def_submodule("enum_${name}");
1424
1425 ''')
1426 if cls.is_class:
1427 code('py::enum_<${enum_name}>(m, "enum_${name}")')
1428 else:
1429 code('py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")')
1430
1431 code.indent()
1432 code.indent()
1433 for val in cls.vals:
1434 code('.value("${val}", ${wrapper_name}::${val})')
1435 code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})')
1436 if not cls.is_class:
1437 code('.export_values()')
1438 code(';')
1439 code.dedent()
1440
1441 code('}')
1442 code.dedent()
1443 code()
1444 code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);')
1445
1446
1447 # Base class for enum types.
1448 class Enum(ParamValue):
1449 __metaclass__ = MetaEnum
1450 vals = []
1451 cmd_line_settable = True
1452
1453 # The name of the wrapping namespace or struct
1454 wrapper_name = 'Enums'
1455
1456 # If true, the enum is wrapped in a struct rather than a namespace
1457 wrapper_is_struct = False
1458
1459 is_class = False
1460
1461 # If not None, use this as the enum name rather than this class name
1462 enum_name = None
1463
1464 def __init__(self, value):
1465 if value not in self.map:
1466 raise TypeError("Enum param got bad value '%s' (not in %s)" \
1467 % (value, self.vals))
1468 self.value = value
1469
1470 def __call__(self, value):
1471 self.__init__(value)
1472 return value
1473
1474 @classmethod
1475 def cxx_predecls(cls, code):
1476 code('#include "enums/$0.hh"', cls.__name__)
1477
1478 @classmethod
1479 def cxx_ini_parse(cls, code, src, dest, ret):
1480 code('if (false) {')
1481 for elem_name in cls.map.keys():
1482 code('} else if (%s == "%s") {' % (src, elem_name))
1483 code.indent()
1484 name = cls.__name__ if cls.enum_name is None else cls.enum_name
1485 code('%s = %s::%s;' % (dest, name if cls.is_class else 'Enums',
1486 elem_name))
1487 code('%s true;' % ret)
1488 code.dedent()
1489 code('} else {')
1490 code(' %s false;' % ret)
1491 code('}')
1492
1493 def getValue(self):
1494 import m5.internal.params
1495 e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__)
1496 return e(self.map[self.value])
1497
1498 def __str__(self):
1499 return self.value
1500
1501 # This param will generate a scoped c++ enum and its python bindings.
1502 class ScopedEnum(Enum):
1503 __metaclass__ = MetaEnum
1504 vals = []
1505 cmd_line_settable = True
1506
1507 # The name of the wrapping namespace or struct
1508 wrapper_name = None
1509
1510 # If true, the enum is wrapped in a struct rather than a namespace
1511 wrapper_is_struct = False
1512
1513 # If true, the generated enum is a scoped enum
1514 is_class = True
1515
1516 # If not None, use this as the enum name rather than this class name
1517 enum_name = None
1518
1519 # how big does a rounding error need to be before we warn about it?
1520 frequency_tolerance = 0.001 # 0.1%
1521
1522 class TickParamValue(NumericParamValue):
1523 cxx_type = 'Tick'
1524 ex_str = "1MHz"
1525 cmd_line_settable = True
1526
1527 @classmethod
1528 def cxx_predecls(cls, code):
1529 code('#include "base/types.hh"')
1530
1531 def __call__(self, value):
1532 self.__init__(value)
1533 return value
1534
1535 def getValue(self):
1536 return long(self.value)
1537
1538 @classmethod
1539 def cxx_ini_predecls(cls, code):
1540 code('#include <sstream>')
1541
1542 # Ticks are expressed in seconds in JSON files and in plain
1543 # Ticks in .ini files. Switch based on a config flag
1544 @classmethod
1545 def cxx_ini_parse(self, code, src, dest, ret):
1546 code('${ret} to_number(${src}, ${dest});')
1547
1548 class Latency(TickParamValue):
1549 ex_str = "100ns"
1550
1551 def __init__(self, value):
1552 if isinstance(value, (Latency, Clock)):
1553 self.ticks = value.ticks
1554 self.value = value.value
1555 elif isinstance(value, Frequency):
1556 self.ticks = value.ticks
1557 self.value = 1.0 / value.value
1558 elif value.endswith('t'):
1559 self.ticks = True
1560 self.value = int(value[:-1])
1561 else:
1562 self.ticks = False
1563 self.value = convert.toLatency(value)
1564
1565 def __call__(self, value):
1566 self.__init__(value)
1567 return value
1568
1569 def __getattr__(self, attr):
1570 if attr in ('latency', 'period'):
1571 return self
1572 if attr == 'frequency':
1573 return Frequency(self)
1574 raise AttributeError("Latency object has no attribute '%s'" % attr)
1575
1576 def getValue(self):
1577 if self.ticks or self.value == 0:
1578 value = self.value
1579 else:
1580 value = ticks.fromSeconds(self.value)
1581 return long(value)
1582
1583 def config_value(self):
1584 return self.getValue()
1585
1586 # convert latency to ticks
1587 def ini_str(self):
1588 return '%d' % self.getValue()
1589
1590 class Frequency(TickParamValue):
1591 ex_str = "1GHz"
1592
1593 def __init__(self, value):
1594 if isinstance(value, (Latency, Clock)):
1595 if value.value == 0:
1596 self.value = 0
1597 else:
1598 self.value = 1.0 / value.value
1599 self.ticks = value.ticks
1600 elif isinstance(value, Frequency):
1601 self.value = value.value
1602 self.ticks = value.ticks
1603 else:
1604 self.ticks = False
1605 self.value = convert.toFrequency(value)
1606
1607 def __call__(self, value):
1608 self.__init__(value)
1609 return value
1610
1611 def __getattr__(self, attr):
1612 if attr == 'frequency':
1613 return self
1614 if attr in ('latency', 'period'):
1615 return Latency(self)
1616 raise AttributeError("Frequency object has no attribute '%s'" % attr)
1617
1618 # convert latency to ticks
1619 def getValue(self):
1620 if self.ticks or self.value == 0:
1621 value = self.value
1622 else:
1623 value = ticks.fromSeconds(1.0 / self.value)
1624 return long(value)
1625
1626 def config_value(self):
1627 return self.getValue()
1628
1629 def ini_str(self):
1630 return '%d' % self.getValue()
1631
1632 # A generic Frequency and/or Latency value. Value is stored as a
1633 # latency, just like Latency and Frequency.
1634 class Clock(TickParamValue):
1635 def __init__(self, value):
1636 if isinstance(value, (Latency, Clock)):
1637 self.ticks = value.ticks
1638 self.value = value.value
1639 elif isinstance(value, Frequency):
1640 self.ticks = value.ticks
1641 self.value = 1.0 / value.value
1642 elif value.endswith('t'):
1643 self.ticks = True
1644 self.value = int(value[:-1])
1645 else:
1646 self.ticks = False
1647 self.value = convert.anyToLatency(value)
1648
1649 def __call__(self, value):
1650 self.__init__(value)
1651 return value
1652
1653 def __str__(self):
1654 return "%s" % Latency(self)
1655
1656 def __getattr__(self, attr):
1657 if attr == 'frequency':
1658 return Frequency(self)
1659 if attr in ('latency', 'period'):
1660 return Latency(self)
1661 raise AttributeError("Frequency object has no attribute '%s'" % attr)
1662
1663 def getValue(self):
1664 return self.period.getValue()
1665
1666 def config_value(self):
1667 return self.period.config_value()
1668
1669 def ini_str(self):
1670 return self.period.ini_str()
1671
1672 class Voltage(Float):
1673 ex_str = "1V"
1674
1675 def __new__(cls, value):
1676 value = convert.toVoltage(value)
1677 return super(cls, Voltage).__new__(cls, value)
1678
1679 def __init__(self, value):
1680 value = convert.toVoltage(value)
1681 super(Voltage, self).__init__(value)
1682
1683 class Current(Float):
1684 ex_str = "1mA"
1685
1686 def __new__(cls, value):
1687 value = convert.toCurrent(value)
1688 return super(cls, Current).__new__(cls, value)
1689
1690 def __init__(self, value):
1691 value = convert.toCurrent(value)
1692 super(Current, self).__init__(value)
1693
1694 class Energy(Float):
1695 ex_str = "1pJ"
1696
1697 def __new__(cls, value):
1698 value = convert.toEnergy(value)
1699 return super(cls, Energy).__new__(cls, value)
1700
1701 def __init__(self, value):
1702 value = convert.toEnergy(value)
1703 super(Energy, self).__init__(value)
1704
1705 class NetworkBandwidth(float,ParamValue):
1706 cxx_type = 'float'
1707 ex_str = "1Gbps"
1708 cmd_line_settable = True
1709
1710 def __new__(cls, value):
1711 # convert to bits per second
1712 val = convert.toNetworkBandwidth(value)
1713 return super(cls, NetworkBandwidth).__new__(cls, val)
1714
1715 def __str__(self):
1716 return str(self.val)
1717
1718 def __call__(self, value):
1719 val = convert.toNetworkBandwidth(value)
1720 self.__init__(val)
1721 return value
1722
1723 def getValue(self):
1724 # convert to seconds per byte
1725 value = 8.0 / float(self)
1726 # convert to ticks per byte
1727 value = ticks.fromSeconds(value)
1728 return float(value)
1729
1730 def ini_str(self):
1731 return '%f' % self.getValue()
1732
1733 def config_value(self):
1734 return '%f' % self.getValue()
1735
1736 @classmethod
1737 def cxx_ini_predecls(cls, code):
1738 code('#include <sstream>')
1739
1740 @classmethod
1741 def cxx_ini_parse(self, code, src, dest, ret):
1742 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
1743
1744 class MemoryBandwidth(float,ParamValue):
1745 cxx_type = 'float'
1746 ex_str = "1GB/s"
1747 cmd_line_settable = True
1748
1749 def __new__(cls, value):
1750 # convert to bytes per second
1751 val = convert.toMemoryBandwidth(value)
1752 return super(cls, MemoryBandwidth).__new__(cls, val)
1753
1754 def __call__(self, value):
1755 val = convert.toMemoryBandwidth(value)
1756 self.__init__(val)
1757 return value
1758
1759 def getValue(self):
1760 # convert to seconds per byte
1761 value = float(self)
1762 if value:
1763 value = 1.0 / float(self)
1764 # convert to ticks per byte
1765 value = ticks.fromSeconds(value)
1766 return float(value)
1767
1768 def ini_str(self):
1769 return '%f' % self.getValue()
1770
1771 def config_value(self):
1772 return '%f' % self.getValue()
1773
1774 @classmethod
1775 def cxx_ini_predecls(cls, code):
1776 code('#include <sstream>')
1777
1778 @classmethod
1779 def cxx_ini_parse(self, code, src, dest, ret):
1780 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
1781
1782 #
1783 # "Constants"... handy aliases for various values.
1784 #
1785
1786 # Special class for NULL pointers. Note the special check in
1787 # make_param_value() above that lets these be assigned where a
1788 # SimObject is required.
1789 # only one copy of a particular node
1790 class NullSimObject(object):
1791 __metaclass__ = Singleton
1792 _name = 'Null'
1793
1794 def __call__(cls):
1795 return cls
1796
1797 def _instantiate(self, parent = None, path = ''):
1798 pass
1799
1800 def ini_str(self):
1801 return 'Null'
1802
1803 def unproxy(self, base):
1804 return self
1805
1806 def set_path(self, parent, name):
1807 pass
1808
1809 def set_parent(self, parent, name):
1810 pass
1811
1812 def clear_parent(self, old_parent):
1813 pass
1814
1815 def descendants(self):
1816 return
1817 yield None
1818
1819 def get_config_as_dict(self):
1820 return {}
1821
1822 def __str__(self):
1823 return self._name
1824
1825 def config_value(self):
1826 return None
1827
1828 def getValue(self):
1829 return None
1830
1831 # The only instance you'll ever need...
1832 NULL = NullSimObject()
1833
1834 def isNullPointer(value):
1835 return isinstance(value, NullSimObject)
1836
1837 # Some memory range specifications use this as a default upper bound.
1838 MaxAddr = Addr.max
1839 MaxTick = Tick.max
1840 AllMemory = AddrRange(0, MaxAddr)
1841
1842
1843 #####################################################################
1844 #
1845 # Port objects
1846 #
1847 # Ports are used to interconnect objects in the memory system.
1848 #
1849 #####################################################################
1850
1851 # Port reference: encapsulates a reference to a particular port on a
1852 # particular SimObject.
1853 class PortRef(object):
1854 def __init__(self, simobj, name, role, is_source):
1855 assert(isSimObject(simobj) or isSimObjectClass(simobj))
1856 self.simobj = simobj
1857 self.name = name
1858 self.role = role
1859 self.is_source = is_source
1860 self.peer = None # not associated with another port yet
1861 self.ccConnected = False # C++ port connection done?
1862 self.index = -1 # always -1 for non-vector ports
1863
1864 def __str__(self):
1865 return '%s.%s' % (self.simobj, self.name)
1866
1867 def __len__(self):
1868 # Return the number of connected ports, i.e. 0 is we have no
1869 # peer and 1 if we do.
1870 return int(self.peer != None)
1871
1872 # for config.ini, print peer's name (not ours)
1873 def ini_str(self):
1874 return str(self.peer)
1875
1876 # for config.json
1877 def get_config_as_dict(self):
1878 return {'role' : self.role, 'peer' : str(self.peer),
1879 'is_source' : str(self.is_source)}
1880
1881 def __getattr__(self, attr):
1882 if attr == 'peerObj':
1883 # shorthand for proxies
1884 return self.peer.simobj
1885 raise AttributeError("'%s' object has no attribute '%s'" % \
1886 (self.__class__.__name__, attr))
1887
1888 # Full connection is symmetric (both ways). Called via
1889 # SimObject.__setattr__ as a result of a port assignment, e.g.,
1890 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
1891 # e.g., "obj1.portA[3] = obj2.portB".
1892 def connect(self, other):
1893 if isinstance(other, VectorPortRef):
1894 # reference to plain VectorPort is implicit append
1895 other = other._get_next()
1896 if self.peer and not proxy.isproxy(self.peer):
1897 fatal("Port %s is already connected to %s, cannot connect %s\n",
1898 self, self.peer, other);
1899 self.peer = other
1900
1901 if proxy.isproxy(other):
1902 other.set_param_desc(PortParamDesc())
1903 return
1904 elif not isinstance(other, PortRef):
1905 raise TypeError("assigning non-port reference '%s' to port '%s'" \
1906 % (other, self))
1907
1908 if not Port.is_compat(self, other):
1909 fatal("Ports %s and %s with roles '%s' and '%s' "
1910 "are not compatible", self, other, self.role, other.role)
1911
1912 if other.peer is not self:
1913 other.connect(self)
1914
1915 # Allow a compatible port pair to be spliced between a port and its
1916 # connected peer. Useful operation for connecting instrumentation
1917 # structures into a system when it is necessary to connect the
1918 # instrumentation after the full system has been constructed.
1919 def splice(self, new_1, new_2):
1920 if not self.peer or proxy.isproxy(self.peer):
1921 fatal("Port %s not connected, cannot splice in new peers\n", self)
1922
1923 if not isinstance(new_1, PortRef) or not isinstance(new_2, PortRef):
1924 raise TypeError(
1925 "Splicing non-port references '%s','%s' to port '%s'" % \
1926 (new_1, new_2, self))
1927
1928 old_peer = self.peer
1929
1930 if Port.is_compat(old_peer, new_1) and Port.is_compat(self, new_2):
1931 old_peer.peer = new_1
1932 new_1.peer = old_peer
1933 self.peer = new_2
1934 new_2.peer = self
1935 elif Port.is_compat(old_peer, new_2) and Port.is_compat(self, new_1):
1936 old_peer.peer = new_2
1937 new_2.peer = old_peer
1938 self.peer = new_1
1939 new_1.peer = self
1940 else:
1941 fatal("Ports %s(%s) and %s(%s) can't be compatibly spliced with "
1942 "%s(%s) and %s(%s)", self, self.role,
1943 old_peer, old_peer.role, new_1, new_1.role,
1944 new_2, new_2.role)
1945
1946 def clone(self, simobj, memo):
1947 if self in memo:
1948 return memo[self]
1949 newRef = copy.copy(self)
1950 memo[self] = newRef
1951 newRef.simobj = simobj
1952 assert(isSimObject(newRef.simobj))
1953 if self.peer and not proxy.isproxy(self.peer):
1954 peerObj = self.peer.simobj(_memo=memo)
1955 newRef.peer = self.peer.clone(peerObj, memo)
1956 assert(not isinstance(newRef.peer, VectorPortRef))
1957 return newRef
1958
1959 def unproxy(self, simobj):
1960 assert(simobj is self.simobj)
1961 if proxy.isproxy(self.peer):
1962 try:
1963 realPeer = self.peer.unproxy(self.simobj)
1964 except:
1965 print("Error in unproxying port '%s' of %s" %
1966 (self.name, self.simobj.path()))
1967 raise
1968 self.connect(realPeer)
1969
1970 # Call C++ to create corresponding port connection between C++ objects
1971 def ccConnect(self):
1972 if self.ccConnected: # already done this
1973 return
1974
1975 peer = self.peer
1976 if not self.peer: # nothing to connect to
1977 return
1978
1979 port = self.simobj.getPort(self.name, self.index)
1980 peer_port = peer.simobj.getPort(peer.name, peer.index)
1981 port.bind(peer_port)
1982
1983 self.ccConnected = True
1984
1985 # A reference to an individual element of a VectorPort... much like a
1986 # PortRef, but has an index.
1987 class VectorPortElementRef(PortRef):
1988 def __init__(self, simobj, name, role, is_source, index):
1989 PortRef.__init__(self, simobj, name, role, is_source)
1990 self.index = index
1991
1992 def __str__(self):
1993 return '%s.%s[%d]' % (self.simobj, self.name, self.index)
1994
1995 # A reference to a complete vector-valued port (not just a single element).
1996 # Can be indexed to retrieve individual VectorPortElementRef instances.
1997 class VectorPortRef(object):
1998 def __init__(self, simobj, name, role, is_source):
1999 assert(isSimObject(simobj) or isSimObjectClass(simobj))
2000 self.simobj = simobj
2001 self.name = name
2002 self.role = role
2003 self.is_source = is_source
2004 self.elements = []
2005
2006 def __str__(self):
2007 return '%s.%s[:]' % (self.simobj, self.name)
2008
2009 def __len__(self):
2010 # Return the number of connected peers, corresponding the the
2011 # length of the elements.
2012 return len(self.elements)
2013
2014 # for config.ini, print peer's name (not ours)
2015 def ini_str(self):
2016 return ' '.join([el.ini_str() for el in self.elements])
2017
2018 # for config.json
2019 def get_config_as_dict(self):
2020 return {'role' : self.role,
2021 'peer' : [el.ini_str() for el in self.elements],
2022 'is_source' : str(self.is_source)}
2023
2024 def __getitem__(self, key):
2025 if not isinstance(key, int):
2026 raise TypeError("VectorPort index must be integer")
2027 if key >= len(self.elements):
2028 # need to extend list
2029 ext = [VectorPortElementRef(
2030 self.simobj, self.name, self.role, self.is_source, i)
2031 for i in range(len(self.elements), key+1)]
2032 self.elements.extend(ext)
2033 return self.elements[key]
2034
2035 def _get_next(self):
2036 return self[len(self.elements)]
2037
2038 def __setitem__(self, key, value):
2039 if not isinstance(key, int):
2040 raise TypeError("VectorPort index must be integer")
2041 self[key].connect(value)
2042
2043 def connect(self, other):
2044 if isinstance(other, (list, tuple)):
2045 # Assign list of port refs to vector port.
2046 # For now, append them... not sure if that's the right semantics
2047 # or if it should replace the current vector.
2048 for ref in other:
2049 self._get_next().connect(ref)
2050 else:
2051 # scalar assignment to plain VectorPort is implicit append
2052 self._get_next().connect(other)
2053
2054 def clone(self, simobj, memo):
2055 if self in memo:
2056 return memo[self]
2057 newRef = copy.copy(self)
2058 memo[self] = newRef
2059 newRef.simobj = simobj
2060 assert(isSimObject(newRef.simobj))
2061 newRef.elements = [el.clone(simobj, memo) for el in self.elements]
2062 return newRef
2063
2064 def unproxy(self, simobj):
2065 [el.unproxy(simobj) for el in self.elements]
2066
2067 def ccConnect(self):
2068 [el.ccConnect() for el in self.elements]
2069
2070 # Port description object. Like a ParamDesc object, this represents a
2071 # logical port in the SimObject class, not a particular port on a
2072 # SimObject instance. The latter are represented by PortRef objects.
2073 class Port(object):
2074 # Port("role", "description")
2075
2076 _compat_dict = { }
2077
2078 @classmethod
2079 def compat(cls, role, peer):
2080 cls._compat_dict.setdefault(role, set()).add(peer)
2081 cls._compat_dict.setdefault(peer, set()).add(role)
2082
2083 @classmethod
2084 def is_compat(cls, one, two):
2085 for port in one, two:
2086 if not port.role in Port._compat_dict:
2087 fatal("Unrecognized role '%s' for port %s\n", port.role, port)
2088 return one.role in Port._compat_dict[two.role]
2089
2090 def __init__(self, role, desc, is_source=False):
2091 self.desc = desc
2092 self.role = role
2093 self.is_source = is_source
2094
2095 # Generate a PortRef for this port on the given SimObject with the
2096 # given name
2097 def makeRef(self, simobj):
2098 return PortRef(simobj, self.name, self.role, self.is_source)
2099
2100 # Connect an instance of this port (on the given SimObject with
2101 # the given name) with the port described by the supplied PortRef
2102 def connect(self, simobj, ref):
2103 self.makeRef(simobj).connect(ref)
2104
2105 # No need for any pre-declarations at the moment as we merely rely
2106 # on an unsigned int.
2107 def cxx_predecls(self, code):
2108 pass
2109
2110 def pybind_predecls(self, code):
2111 cls.cxx_predecls(self, code)
2112
2113 # Declare an unsigned int with the same name as the port, that
2114 # will eventually hold the number of connected ports (and thus the
2115 # number of elements for a VectorPort).
2116 def cxx_decl(self, code):
2117 code('unsigned int port_${{self.name}}_connection_count;')
2118
2119 Port.compat('GEM5 REQUESTER', 'GEM5 RESPONDER')
2120
2121 class RequestPort(Port):
2122 # RequestPort("description")
2123 def __init__(self, desc):
2124 super(RequestPort, self).__init__(
2125 'GEM5 REQUESTER', desc, is_source=True)
2126
2127 class ResponsePort(Port):
2128 # ResponsePort("description")
2129 def __init__(self, desc):
2130 super(ResponsePort, self).__init__('GEM5 RESPONDER', desc)
2131
2132 # VectorPort description object. Like Port, but represents a vector
2133 # of connections (e.g., as on a XBar).
2134 class VectorPort(Port):
2135 def makeRef(self, simobj):
2136 return VectorPortRef(simobj, self.name, self.role, self.is_source)
2137
2138 class VectorRequestPort(VectorPort):
2139 # VectorRequestPort("description")
2140 def __init__(self, desc):
2141 super(VectorRequestPort, self).__init__(
2142 'GEM5 REQUESTER', desc, is_source=True)
2143
2144 class VectorResponsePort(VectorPort):
2145 # VectorResponsePort("description")
2146 def __init__(self, desc):
2147 super(VectorResponsePort, self).__init__('GEM5 RESPONDER', desc)
2148
2149 # Old names, maintained for compatibility.
2150 MasterPort = RequestPort
2151 SlavePort = ResponsePort
2152 VectorMasterPort = VectorRequestPort
2153 VectorSlavePort = VectorResponsePort
2154
2155 # 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
2156 # proxy objects (via set_param_desc()) so that proxy error messages
2157 # make sense.
2158 class PortParamDesc(object):
2159 __metaclass__ = Singleton
2160
2161 ptype_str = 'Port'
2162 ptype = Port
2163
2164 baseEnums = allEnums.copy()
2165 baseParams = allParams.copy()
2166
2167 def clear():
2168 global allEnums, allParams
2169
2170 allEnums = baseEnums.copy()
2171 allParams = baseParams.copy()
2172
2173 __all__ = ['Param', 'VectorParam',
2174 'Enum', 'ScopedEnum', 'Bool', 'String', 'Float',
2175 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
2176 'Int32', 'UInt32', 'Int64', 'UInt64',
2177 'Counter', 'Addr', 'Tick', 'Percent',
2178 'TcpPort', 'UdpPort', 'EthernetAddr',
2179 'IpAddress', 'IpNetmask', 'IpWithPort',
2180 'MemorySize', 'MemorySize32',
2181 'Latency', 'Frequency', 'Clock', 'Voltage', 'Current', 'Energy',
2182 'NetworkBandwidth', 'MemoryBandwidth',
2183 'AddrRange',
2184 'MaxAddr', 'MaxTick', 'AllMemory',
2185 'Time',
2186 'NextEthernetAddr', 'NULL',
2187 'Port', 'RequestPort', 'ResponsePort', 'MasterPort', 'SlavePort',
2188 'VectorPort', 'VectorRequestPort', 'VectorResponsePort',
2189 'VectorMasterPort', 'VectorSlavePort']