88d38f87ab4e170811fc2d8bb675c1c9f3bdea00
1 # Copyright (c) 2012-2013 ARM Limited
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.
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.
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.
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.
40 # Authors: Steve Reinhardt
45 #####################################################################
47 # Parameter description classes
49 # The _params dictionary in each class maps parameter names to either
50 # a Param or a VectorParam object. These objects contain the
51 # parameter description string, the parameter type, and the default
52 # value (if any). The convert() method on these objects is used to
53 # force whatever value is assigned to the parameter to the appropriate
56 # Note that the default values are loaded into the class's attribute
57 # space when the parameter dictionary is initialized (in
58 # MetaSimObject._new_param()); after that point they aren't used.
60 #####################################################################
73 def isSimObject(*args
, **kwargs
):
74 return SimObject
.isSimObject(*args
, **kwargs
)
76 def isSimObjectSequence(*args
, **kwargs
):
77 return SimObject
.isSimObjectSequence(*args
, **kwargs
)
79 def isSimObjectClass(*args
, **kwargs
):
80 return SimObject
.isSimObjectClass(*args
, **kwargs
)
84 class MetaParamValue(type):
85 def __new__(mcls
, name
, bases
, dct
):
86 cls
= super(MetaParamValue
, mcls
).__new
__(mcls
, name
, bases
, dct
)
87 assert name
not in allParams
92 # Dummy base class to identify types that are legitimate for SimObject
94 class ParamValue(object):
95 __metaclass__
= MetaParamValue
96 cmd_line_settable
= False
98 # Generate the code needed as a prerequisite for declaring a C++
99 # object of this type. Typically generates one or more #include
100 # statements. Used when declaring parameters of this type.
102 def cxx_predecls(cls
, code
):
105 # Generate the code needed as a prerequisite for including a
106 # reference to a C++ object of this type in a SWIG .i file.
107 # Typically generates one or more %import or %include statements.
109 def swig_predecls(cls
, code
):
112 # default for printing to .ini file is regular string conversion.
113 # will be overridden in some cases
117 # allows us to blithely call unproxy() on things without checking
118 # if they're really proxies or not
119 def unproxy(self
, base
):
122 # Produce a human readable version of the stored value
123 def pretty_print(self
, value
):
126 # Regular parameter description.
127 class ParamDesc(object):
128 def __init__(self
, ptype_str
, ptype
, *args
, **kwargs
):
129 self
.ptype_str
= ptype_str
130 # remember ptype only if it is provided
138 self
.default
= args
[0]
141 raise TypeError, 'too many arguments'
143 if kwargs
.has_key('desc'):
144 assert(not hasattr(self
, 'desc'))
145 self
.desc
= kwargs
['desc']
148 if kwargs
.has_key('default'):
149 assert(not hasattr(self
, 'default'))
150 self
.default
= kwargs
['default']
151 del kwargs
['default']
154 raise TypeError, 'extra unknown kwargs %s' % kwargs
156 if not hasattr(self
, 'desc'):
157 raise TypeError, 'desc attribute missing'
159 def __getattr__(self
, attr
):
161 ptype
= SimObject
.allClasses
[self
.ptype_str
]
162 assert isSimObjectClass(ptype
)
166 raise AttributeError, "'%s' object has no attribute '%s'" % \
167 (type(self
).__name
__, attr
)
169 def example_str(self
):
170 if hasattr(self
.ptype
, "ex_str"):
171 return self
.ptype
.ex_str
173 return self
.ptype_str
175 # Is the param available to be exposed on the command line
176 def isCmdLineSettable(self
):
177 if hasattr(self
.ptype
, "cmd_line_settable"):
178 return self
.ptype
.cmd_line_settable
182 def convert(self
, value
):
183 if isinstance(value
, proxy
.BaseProxy
):
184 value
.set_param_desc(self
)
186 if not hasattr(self
, 'ptype') and isNullPointer(value
):
187 # deferred evaluation of SimObject; continue to defer if
188 # we're just assigning a null pointer
190 if isinstance(value
, self
.ptype
):
192 if isNullPointer(value
) and isSimObjectClass(self
.ptype
):
194 return self
.ptype(value
)
196 def pretty_print(self
, value
):
197 if isinstance(value
, proxy
.BaseProxy
):
199 if isNullPointer(value
):
201 return self
.ptype(value
).pretty_print(value
)
203 def cxx_predecls(self
, code
):
204 code('#include <cstddef>')
205 self
.ptype
.cxx_predecls(code
)
207 def swig_predecls(self
, code
):
208 self
.ptype
.swig_predecls(code
)
210 def cxx_decl(self
, code
):
211 code('${{self.ptype.cxx_type}} ${{self.name}};')
213 # Vector-valued parameter description. Just like ParamDesc, except
214 # that the value is a vector (list) of the specified type instead of a
217 class VectorParamValue(list):
218 __metaclass__
= MetaParamValue
219 def __setattr__(self
, attr
, value
):
220 raise AttributeError, \
221 "Not allowed to set %s on '%s'" % (attr
, type(self
).__name
__)
224 return ' '.join([v
.ini_str() for v
in self
])
227 return [ v
.getValue() for v
in self
]
229 def unproxy(self
, base
):
230 if len(self
) == 1 and isinstance(self
[0], proxy
.AllProxy
):
231 return self
[0].unproxy(base
)
233 return [v
.unproxy(base
) for v
in self
]
235 class SimObjectVector(VectorParamValue
):
236 # support clone operation
237 def __call__(self
, **kwargs
):
238 return SimObjectVector([v(**kwargs
) for v
in self
])
240 def clear_parent(self
, old_parent
):
242 v
.clear_parent(old_parent
)
244 def set_parent(self
, parent
, name
):
246 self
[0].set_parent(parent
, name
)
248 width
= int(math
.ceil(math
.log(len(self
))/math
.log(10)))
249 for i
,v
in enumerate(self
):
250 v
.set_parent(parent
, "%s%0*d" % (name
, width
, i
))
252 def has_parent(self
):
253 return reduce(lambda x
,y
: x
and y
, [v
.has_parent() for v
in self
])
255 # return 'cpu0 cpu1' etc. for print_ini()
257 return ' '.join([v
._name
for v
in self
])
259 # By iterating through the constituent members of the vector here
260 # we can nicely handle iterating over all a SimObject's children
261 # without having to provide lots of special functions on
262 # SimObjectVector directly.
263 def descendants(self
):
265 for obj
in v
.descendants():
268 def get_config_as_dict(self
):
271 a
.append(v
.get_config_as_dict())
274 # If we are replacing an item in the vector, make sure to set the
275 # parent reference of the new SimObject to be the same as the parent
276 # of the SimObject being replaced. Useful to have if we created
277 # a SimObjectVector of temporary objects that will be modified later in
278 # configuration scripts.
279 def __setitem__(self
, key
, value
):
281 if value
.has_parent():
282 warn("SimObject %s already has a parent" % value
.get_name() +\
283 " that is being overwritten by a SimObjectVector")
284 value
.set_parent(val
.get_parent(), val
._name
)
285 super(SimObjectVector
, self
).__setitem
__(key
, value
)
287 # Enumerate the params of each member of the SimObject vector. Creates
288 # strings that will allow indexing into the vector by the python code and
289 # allow it to be specified on the command line.
290 def enumerateParams(self
, flags_dict
= {},
293 if hasattr(self
, "_paramEnumed"):
294 print "Cycle detected enumerating params at %s?!" % (cmd_line_str
)
298 # Each entry in the SimObjectVector should be an
299 # instance of a SimObject
300 flags_dict
= vals
.enumerateParams(flags_dict
,
301 cmd_line_str
+ "%d." % x
,
302 access_str
+ "[%d]." % x
)
307 class VectorParamDesc(ParamDesc
):
308 # Convert assigned value to appropriate type. If the RHS is not a
309 # list or tuple, it generates a single-element list.
310 def convert(self
, value
):
311 if isinstance(value
, (list, tuple)):
312 # list: coerce each element into new list
313 tmp_list
= [ ParamDesc
.convert(self
, v
) for v
in value
]
315 # singleton: coerce to a single-element list
316 tmp_list
= [ ParamDesc
.convert(self
, value
) ]
318 if isSimObjectSequence(tmp_list
):
319 return SimObjectVector(tmp_list
)
321 return VectorParamValue(tmp_list
)
323 # Produce a human readable example string that describes
324 # how to set this vector parameter in the absence of a default
326 def example_str(self
):
327 s
= super(VectorParamDesc
, self
).example_str()
328 help_str
= "[" + s
+ "," + s
+ ", ...]"
331 # Produce a human readable representation of the value of this vector param.
332 def pretty_print(self
, value
):
333 if isinstance(value
, (list, tuple)):
334 tmp_list
= [ ParamDesc
.pretty_print(self
, v
) for v
in value
]
335 elif isinstance(value
, str):
336 tmp_list
= [ ParamDesc
.pretty_print(self
, v
) for v
in value
.split(',') ]
338 tmp_list
= [ ParamDesc
.pretty_print(self
, value
) ]
342 # This is a helper function for the new config system
343 def __call__(self
, value
):
344 if isinstance(value
, (list, tuple)):
345 # list: coerce each element into new list
346 tmp_list
= [ ParamDesc
.convert(self
, v
) for v
in value
]
347 elif isinstance(value
, str):
348 # If input is a csv string
349 tmp_list
= [ ParamDesc
.convert(self
, v
) for v
in value
.split(',') ]
351 # singleton: coerce to a single-element list
352 tmp_list
= [ ParamDesc
.convert(self
, value
) ]
354 return VectorParamValue(tmp_list
)
356 def swig_module_name(self
):
357 return "%s_vector" % self
.ptype_str
359 def swig_predecls(self
, code
):
360 code('%import "${{self.swig_module_name()}}.i"')
362 def swig_decl(self
, code
):
363 code('%module(package="m5.internal") ${{self.swig_module_name()}}')
365 self
.ptype
.cxx_predecls(code
)
368 # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion
369 code('%include "std_container.i"')
371 self
.ptype
.swig_predecls(code
)
373 code('%include "std_vector.i"')
376 ptype
= self
.ptype_str
377 cxx_type
= self
.ptype
.cxx_type
379 code('%template(vector_$ptype) std::vector< $cxx_type >;')
381 def cxx_predecls(self
, code
):
382 code('#include <vector>')
383 self
.ptype
.cxx_predecls(code
)
385 def cxx_decl(self
, code
):
386 code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
388 class ParamFactory(object):
389 def __init__(self
, param_desc_class
, ptype_str
= None):
390 self
.param_desc_class
= param_desc_class
391 self
.ptype_str
= ptype_str
393 def __getattr__(self
, attr
):
395 attr
= self
.ptype_str
+ '.' + attr
396 return ParamFactory(self
.param_desc_class
, attr
)
398 # E.g., Param.Int(5, "number of widgets")
399 def __call__(self
, *args
, **kwargs
):
402 ptype
= allParams
[self
.ptype_str
]
404 # if name isn't defined yet, assume it's a SimObject, and
405 # try to resolve it later
407 return self
.param_desc_class(self
.ptype_str
, ptype
, *args
, **kwargs
)
409 Param
= ParamFactory(ParamDesc
)
410 VectorParam
= ParamFactory(VectorParamDesc
)
412 #####################################################################
416 # Though native Python types could be used to specify parameter types
417 # (the 'ptype' field of the Param and VectorParam classes), it's more
418 # flexible to define our own set of types. This gives us more control
419 # over how Python expressions are converted to values (via the
420 # __init__() constructor) and how these values are printed out (via
421 # the __str__() conversion method).
423 #####################################################################
425 # String-valued parameter. Just mixin the ParamValue class with the
426 # built-in str class.
427 class String(ParamValue
,str):
428 cxx_type
= 'std::string'
429 cmd_line_settable
= True
432 def cxx_predecls(self
, code
):
433 code('#include <string>')
436 def swig_predecls(cls
, code
):
437 code('%include "std_string.i"')
439 def __call__(self
, value
):
446 # superclass for "numeric" parameter values, to emulate math
447 # operations in a type-safe way. e.g., a Latency times an int returns
448 # a new Latency object.
449 class NumericParamValue(ParamValue
):
451 return str(self
.value
)
454 return float(self
.value
)
457 return long(self
.value
)
460 return int(self
.value
)
462 # hook for bounds checking
466 def __mul__(self
, other
):
467 newobj
= self
.__class
__(self
)
468 newobj
.value
*= other
474 def __div__(self
, other
):
475 newobj
= self
.__class
__(self
)
476 newobj
.value
/= other
480 def __sub__(self
, other
):
481 newobj
= self
.__class
__(self
)
482 newobj
.value
-= other
486 # Metaclass for bounds-checked integer parameters. See CheckedInt.
487 class CheckedIntType(MetaParamValue
):
488 def __init__(cls
, name
, bases
, dict):
489 super(CheckedIntType
, cls
).__init
__(name
, bases
, dict)
491 # CheckedInt is an abstract base class, so we actually don't
492 # want to do any processing on it... the rest of this code is
493 # just for classes that derive from CheckedInt.
494 if name
== 'CheckedInt':
497 if not (hasattr(cls
, 'min') and hasattr(cls
, 'max')):
498 if not (hasattr(cls
, 'size') and hasattr(cls
, 'unsigned')):
499 panic("CheckedInt subclass %s must define either\n" \
500 " 'min' and 'max' or 'size' and 'unsigned'\n",
504 cls
.max = 2 ** cls
.size
- 1
506 cls
.min = -(2 ** (cls
.size
- 1))
507 cls
.max = (2 ** (cls
.size
- 1)) - 1
509 # Abstract superclass for bounds-checked integer parameters. This
510 # class is subclassed to generate parameter classes with specific
511 # bounds. Initialization of the min and max bounds is done in the
512 # metaclass CheckedIntType.__init__.
513 class CheckedInt(NumericParamValue
):
514 __metaclass__
= CheckedIntType
515 cmd_line_settable
= True
518 if not self
.min <= self
.value
<= self
.max:
519 raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
520 (self
.min, self
.value
, self
.max)
522 def __init__(self
, value
):
523 if isinstance(value
, str):
524 self
.value
= convert
.toInteger(value
)
525 elif isinstance(value
, (int, long, float, NumericParamValue
)):
526 self
.value
= long(value
)
528 raise TypeError, "Can't convert object of type %s to CheckedInt" \
529 % type(value
).__name
__
532 def __call__(self
, value
):
537 def cxx_predecls(cls
, code
):
538 # most derived types require this, so we just do it here once
539 code('#include "base/types.hh"')
542 def swig_predecls(cls
, code
):
543 # most derived types require this, so we just do it here once
544 code('%import "stdint.i"')
545 code('%import "base/types.hh"')
548 return long(self
.value
)
550 class Int(CheckedInt
): cxx_type
= 'int'; size
= 32; unsigned
= False
551 class Unsigned(CheckedInt
): cxx_type
= 'unsigned'; size
= 32; unsigned
= True
553 class Int8(CheckedInt
): cxx_type
= 'int8_t'; size
= 8; unsigned
= False
554 class UInt8(CheckedInt
): cxx_type
= 'uint8_t'; size
= 8; unsigned
= True
555 class Int16(CheckedInt
): cxx_type
= 'int16_t'; size
= 16; unsigned
= False
556 class UInt16(CheckedInt
): cxx_type
= 'uint16_t'; size
= 16; unsigned
= True
557 class Int32(CheckedInt
): cxx_type
= 'int32_t'; size
= 32; unsigned
= False
558 class UInt32(CheckedInt
): cxx_type
= 'uint32_t'; size
= 32; unsigned
= True
559 class Int64(CheckedInt
): cxx_type
= 'int64_t'; size
= 64; unsigned
= False
560 class UInt64(CheckedInt
): cxx_type
= 'uint64_t'; size
= 64; unsigned
= True
562 class Counter(CheckedInt
): cxx_type
= 'Counter'; size
= 64; unsigned
= True
563 class Tick(CheckedInt
): cxx_type
= 'Tick'; size
= 64; unsigned
= True
564 class TcpPort(CheckedInt
): cxx_type
= 'uint16_t'; size
= 16; unsigned
= True
565 class UdpPort(CheckedInt
): cxx_type
= 'uint16_t'; size
= 16; unsigned
= True
567 class Percent(CheckedInt
): cxx_type
= 'int'; min = 0; max = 100
569 class Cycles(CheckedInt
):
575 from m5
.internal
.core
import Cycles
576 return Cycles(self
.value
)
578 class Float(ParamValue
, float):
580 cmdLineSettable
= True
582 def __init__(self
, value
):
583 if isinstance(value
, (int, long, float, NumericParamValue
, Float
, str)):
584 self
.value
= float(value
)
586 raise TypeError, "Can't convert object of type %s to Float" \
587 % type(value
).__name
__
589 def __call__(self
, value
):
594 return float(self
.value
)
596 class MemorySize(CheckedInt
):
597 cxx_type
= 'uint64_t'
601 def __init__(self
, value
):
602 if isinstance(value
, MemorySize
):
603 self
.value
= value
.value
605 self
.value
= convert
.toMemorySize(value
)
608 class MemorySize32(CheckedInt
):
609 cxx_type
= 'uint32_t'
613 def __init__(self
, value
):
614 if isinstance(value
, MemorySize
):
615 self
.value
= value
.value
617 self
.value
= convert
.toMemorySize(value
)
620 class Addr(CheckedInt
):
624 def __init__(self
, value
):
625 if isinstance(value
, Addr
):
626 self
.value
= value
.value
629 self
.value
= convert
.toMemorySize(value
)
631 self
.value
= long(value
)
633 def __add__(self
, other
):
634 if isinstance(other
, Addr
):
635 return self
.value
+ other
.value
637 return self
.value
+ other
638 def pretty_print(self
, value
):
640 val
= convert
.toMemorySize(value
)
643 return "0x%x" % long(val
)
645 class AddrRange(ParamValue
):
646 cxx_type
= 'AddrRange'
648 def __init__(self
, *args
, **kwargs
):
649 # Disable interleaving by default
650 self
.intlvHighBit
= 0
654 def handle_kwargs(self
, kwargs
):
655 # An address range needs to have an upper limit, specified
656 # either explicitly with an end, or as an offset using the
659 self
.end
= Addr(kwargs
.pop('end'))
660 elif 'size' in kwargs
:
661 self
.end
= self
.start
+ Addr(kwargs
.pop('size')) - 1
663 raise TypeError, "Either end or size must be specified"
665 # Now on to the optional bit
666 if 'intlvHighBit' in kwargs
:
667 self
.intlvHighBit
= int(kwargs
.pop('intlvHighBit'))
668 if 'intlvBits' in kwargs
:
669 self
.intlvBits
= int(kwargs
.pop('intlvBits'))
670 if 'intlvMatch' in kwargs
:
671 self
.intlvMatch
= int(kwargs
.pop('intlvMatch'))
674 self
.start
= Addr(kwargs
.pop('start'))
675 handle_kwargs(self
, kwargs
)
679 self
.start
= Addr(args
[0])
680 handle_kwargs(self
, kwargs
)
681 elif isinstance(args
[0], (list, tuple)):
682 self
.start
= Addr(args
[0][0])
683 self
.end
= Addr(args
[0][1])
686 self
.end
= Addr(args
[0]) - 1
689 self
.start
= Addr(args
[0])
690 self
.end
= Addr(args
[1])
692 raise TypeError, "Too many arguments specified"
695 raise TypeError, "Too many keywords: %s" % kwargs
.keys()
698 return '%s:%s' % (self
.start
, self
.end
)
701 # Divide the size by the size of the interleaving slice
702 return (long(self
.end
) - long(self
.start
) + 1) >> self
.intlvBits
705 def cxx_predecls(cls
, code
):
706 Addr
.cxx_predecls(code
)
707 code('#include "base/addr_range.hh"')
710 def swig_predecls(cls
, code
):
711 Addr
.swig_predecls(code
)
714 # Go from the Python class to the wrapped C++ class generated
716 from m5
.internal
.range import AddrRange
718 return AddrRange(long(self
.start
), long(self
.end
),
719 int(self
.intlvHighBit
), int(self
.intlvBits
),
720 int(self
.intlvMatch
))
722 # Boolean parameter type. Python doesn't let you subclass bool, since
723 # it doesn't want to let you create multiple instances of True and
724 # False. Thus this is a little more complicated than String.
725 class Bool(ParamValue
):
727 cmd_line_settable
= True
729 def __init__(self
, value
):
731 self
.value
= convert
.toBool(value
)
733 self
.value
= bool(value
)
735 def __call__(self
, value
):
740 return bool(self
.value
)
743 return str(self
.value
)
745 # implement truth value testing for Bool parameters so that these params
746 # evaluate correctly during the python configuration phase
747 def __nonzero__(self
):
748 return bool(self
.value
)
755 def IncEthernetAddr(addr
, val
= 1):
756 bytes
= map(lambda x
: int(x
, 16), addr
.split(':'))
758 for i
in (5, 4, 3, 2, 1):
759 val
,rem
= divmod(bytes
[i
], 256)
764 assert(bytes
[0] <= 255)
765 return ':'.join(map(lambda x
: '%02x' % x
, bytes
))
767 _NextEthernetAddr
= "00:90:00:00:00:01"
768 def NextEthernetAddr():
769 global _NextEthernetAddr
771 value
= _NextEthernetAddr
772 _NextEthernetAddr
= IncEthernetAddr(_NextEthernetAddr
, 1)
775 class EthernetAddr(ParamValue
):
776 cxx_type
= 'Net::EthAddr'
777 ex_str
= "00:90:00:00:00:01"
778 cmd_line_settable
= True
781 def cxx_predecls(cls
, code
):
782 code('#include "base/inet.hh"')
785 def swig_predecls(cls
, code
):
786 code('%include "python/swig/inet.i"')
788 def __init__(self
, value
):
789 if value
== NextEthernetAddr
:
793 if not isinstance(value
, str):
794 raise TypeError, "expected an ethernet address and didn't get one"
796 bytes
= value
.split(':')
798 raise TypeError, 'invalid ethernet address %s' % value
801 if not 0 <= int(byte
, base
=16) <= 0xff:
802 raise TypeError, 'invalid ethernet address %s' % value
806 def __call__(self
, value
):
810 def unproxy(self
, base
):
811 if self
.value
== NextEthernetAddr
:
812 return EthernetAddr(self
.value())
816 from m5
.internal
.params
import EthAddr
817 return EthAddr(self
.value
)
822 # When initializing an IpAddress, pass in an existing IpAddress, a string of
823 # the form "a.b.c.d", or an integer representing an IP.
824 class IpAddress(ParamValue
):
825 cxx_type
= 'Net::IpAddress'
827 cmd_line_settable
= True
830 def cxx_predecls(cls
, code
):
831 code('#include "base/inet.hh"')
834 def swig_predecls(cls
, code
):
835 code('%include "python/swig/inet.i"')
837 def __init__(self
, value
):
838 if isinstance(value
, IpAddress
):
842 self
.ip
= convert
.toIpAddress(value
)
844 self
.ip
= long(value
)
847 def __call__(self
, value
):
852 tup
= [(self
.ip
>> i
) & 0xff for i
in (24, 16, 8, 0)]
853 return '%d.%d.%d.%d' % tuple(tup
)
855 def __eq__(self
, other
):
856 if isinstance(other
, IpAddress
):
857 return self
.ip
== other
.ip
858 elif isinstance(other
, str):
860 return self
.ip
== convert
.toIpAddress(other
)
864 return self
.ip
== other
866 def __ne__(self
, other
):
867 return not (self
== other
)
870 if self
.ip
< 0 or self
.ip
>= (1 << 32):
871 raise TypeError, "invalid ip address %#08x" % self
.ip
874 from m5
.internal
.params
import IpAddress
875 return IpAddress(self
.ip
)
877 # When initializing an IpNetmask, pass in an existing IpNetmask, a string of
878 # the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as
879 # positional or keyword arguments.
880 class IpNetmask(IpAddress
):
881 cxx_type
= 'Net::IpNetmask'
882 ex_str
= "127.0.0.0/24"
883 cmd_line_settable
= True
886 def cxx_predecls(cls
, code
):
887 code('#include "base/inet.hh"')
890 def swig_predecls(cls
, code
):
891 code('%include "python/swig/inet.i"')
893 def __init__(self
, *args
, **kwargs
):
894 def handle_kwarg(self
, kwargs
, key
, elseVal
= None):
896 setattr(self
, key
, kwargs
.pop(key
))
898 setattr(self
, key
, elseVal
)
900 raise TypeError, "No value set for %s" % key
903 handle_kwarg(self
, kwargs
, 'ip')
904 handle_kwarg(self
, kwargs
, 'netmask')
908 if not 'ip' in kwargs
and not 'netmask' in kwargs
:
909 raise TypeError, "Invalid arguments"
910 handle_kwarg(self
, kwargs
, 'ip', args
[0])
911 handle_kwarg(self
, kwargs
, 'netmask', args
[0])
912 elif isinstance(args
[0], IpNetmask
):
914 self
.netmask
= args
[0].netmask
916 (self
.ip
, self
.netmask
) = convert
.toIpNetmask(args
[0])
920 self
.netmask
= args
[1]
922 raise TypeError, "Too many arguments specified"
925 raise TypeError, "Too many keywords: %s" % kwargs
.keys()
929 def __call__(self
, value
):
934 return "%s/%d" % (super(IpNetmask
, self
).__str
__(), self
.netmask
)
936 def __eq__(self
, other
):
937 if isinstance(other
, IpNetmask
):
938 return self
.ip
== other
.ip
and self
.netmask
== other
.netmask
939 elif isinstance(other
, str):
941 return (self
.ip
, self
.netmask
) == convert
.toIpNetmask(other
)
949 if self
.netmask
< 0 or self
.netmask
> 32:
950 raise TypeError, "invalid netmask %d" % netmask
953 from m5
.internal
.params
import IpNetmask
954 return IpNetmask(self
.ip
, self
.netmask
)
956 # When initializing an IpWithPort, pass in an existing IpWithPort, a string of
957 # the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
958 class IpWithPort(IpAddress
):
959 cxx_type
= 'Net::IpWithPort'
960 ex_str
= "127.0.0.1:80"
961 cmd_line_settable
= True
964 def cxx_predecls(cls
, code
):
965 code('#include "base/inet.hh"')
968 def swig_predecls(cls
, code
):
969 code('%include "python/swig/inet.i"')
971 def __init__(self
, *args
, **kwargs
):
972 def handle_kwarg(self
, kwargs
, key
, elseVal
= None):
974 setattr(self
, key
, kwargs
.pop(key
))
976 setattr(self
, key
, elseVal
)
978 raise TypeError, "No value set for %s" % key
981 handle_kwarg(self
, kwargs
, 'ip')
982 handle_kwarg(self
, kwargs
, 'port')
986 if not 'ip' in kwargs
and not 'port' in kwargs
:
987 raise TypeError, "Invalid arguments"
988 handle_kwarg(self
, kwargs
, 'ip', args
[0])
989 handle_kwarg(self
, kwargs
, 'port', args
[0])
990 elif isinstance(args
[0], IpWithPort
):
992 self
.port
= args
[0].port
994 (self
.ip
, self
.port
) = convert
.toIpWithPort(args
[0])
1000 raise TypeError, "Too many arguments specified"
1003 raise TypeError, "Too many keywords: %s" % kwargs
.keys()
1007 def __call__(self
, value
):
1008 self
.__init
__(value
)
1012 return "%s:%d" % (super(IpWithPort
, self
).__str
__(), self
.port
)
1014 def __eq__(self
, other
):
1015 if isinstance(other
, IpWithPort
):
1016 return self
.ip
== other
.ip
and self
.port
== other
.port
1017 elif isinstance(other
, str):
1019 return (self
.ip
, self
.port
) == convert
.toIpWithPort(other
)
1027 if self
.port
< 0 or self
.port
> 0xffff:
1028 raise TypeError, "invalid port %d" % self
.port
1031 from m5
.internal
.params
import IpWithPort
1032 return IpWithPort(self
.ip
, self
.port
)
1034 time_formats
= [ "%a %b %d %H:%M:%S %Z %Y",
1035 "%a %b %d %H:%M:%S %Z %Y",
1036 "%Y/%m/%d %H:%M:%S",
1039 "%m/%d/%Y %H:%M:%S",
1042 "%m/%d/%y %H:%M:%S",
1047 def parse_time(value
):
1048 from time
import gmtime
, strptime
, struct_time
, time
1049 from datetime
import datetime
, date
1051 if isinstance(value
, struct_time
):
1054 if isinstance(value
, (int, long)):
1055 return gmtime(value
)
1057 if isinstance(value
, (datetime
, date
)):
1058 return value
.timetuple()
1060 if isinstance(value
, str):
1061 if value
in ('Now', 'Today'):
1062 return time
.gmtime(time
.time())
1064 for format
in time_formats
:
1066 return strptime(value
, format
)
1070 raise ValueError, "Could not parse '%s' as a time" % value
1072 class Time(ParamValue
):
1076 def cxx_predecls(cls
, code
):
1077 code('#include <time.h>')
1080 def swig_predecls(cls
, code
):
1081 code('%include "python/swig/time.i"')
1083 def __init__(self
, value
):
1084 self
.value
= parse_time(value
)
1086 def __call__(self
, value
):
1087 self
.__init
__(value
)
1091 from m5
.internal
.params
import tm
1094 py_time
= self
.value
1096 # UNIX is years since 1900
1097 c_time
.tm_year
= py_time
.tm_year
- 1900;
1099 # Python starts at 1, UNIX starts at 0
1100 c_time
.tm_mon
= py_time
.tm_mon
- 1;
1101 c_time
.tm_mday
= py_time
.tm_mday
;
1102 c_time
.tm_hour
= py_time
.tm_hour
;
1103 c_time
.tm_min
= py_time
.tm_min
;
1104 c_time
.tm_sec
= py_time
.tm_sec
;
1106 # Python has 0 as Monday, UNIX is 0 as sunday
1107 c_time
.tm_wday
= py_time
.tm_wday
+ 1
1108 if c_time
.tm_wday
> 6:
1109 c_time
.tm_wday
-= 7;
1111 # Python starts at 1, Unix starts at 0
1112 c_time
.tm_yday
= py_time
.tm_yday
- 1;
1117 return time
.asctime(self
.value
)
1122 def get_config_as_dict(self
):
1125 # Enumerated types are a little more complex. The user specifies the
1126 # type as Enum(foo) where foo is either a list or dictionary of
1127 # alternatives (typically strings, but not necessarily so). (In the
1128 # long run, the integer value of the parameter will be the list index
1129 # or the corresponding dictionary value. For now, since we only check
1130 # that the alternative is valid and then spit it into a .ini file,
1131 # there's not much point in using the dictionary.)
1133 # What Enum() must do is generate a new type encapsulating the
1134 # provided list/dictionary so that specific values of the parameter
1135 # can be instances of that type. We define two hidden internal
1136 # classes (_ListEnum and _DictEnum) to serve as base classes, then
1137 # derive the new type from the appropriate base class on the fly.
1140 # Metaclass for Enum types
1141 class MetaEnum(MetaParamValue
):
1142 def __new__(mcls
, name
, bases
, dict):
1143 assert name
not in allEnums
1145 cls
= super(MetaEnum
, mcls
).__new
__(mcls
, name
, bases
, dict)
1146 allEnums
[name
] = cls
1149 def __init__(cls
, name
, bases
, init_dict
):
1150 if init_dict
.has_key('map'):
1151 if not isinstance(cls
.map, dict):
1152 raise TypeError, "Enum-derived class attribute 'map' " \
1153 "must be of type dict"
1154 # build list of value strings from map
1155 cls
.vals
= cls
.map.keys()
1157 elif init_dict
.has_key('vals'):
1158 if not isinstance(cls
.vals
, list):
1159 raise TypeError, "Enum-derived class attribute 'vals' " \
1160 "must be of type list"
1161 # build string->value map from vals sequence
1163 for idx
,val
in enumerate(cls
.vals
):
1166 raise TypeError, "Enum-derived class must define "\
1167 "attribute 'map' or 'vals'"
1169 cls
.cxx_type
= 'Enums::%s' % name
1171 super(MetaEnum
, cls
).__init
__(name
, bases
, init_dict
)
1173 # Generate C++ class declaration for this enum type.
1174 # Note that we wrap the enum in a class/struct to act as a namespace,
1175 # so that the enum strings can be brief w/o worrying about collisions.
1176 def cxx_decl(cls
, code
):
1177 wrapper_name
= cls
.wrapper_name
1178 wrapper
= 'struct' if cls
.wrapper_is_struct
else 'namespace'
1179 name
= cls
.__name
__ if cls
.enum_name
is None else cls
.enum_name
1180 idem_macro
= '__ENUM__%s__%s__' % (wrapper_name
, name
)
1186 $wrapper $wrapper_name {
1190 for val
in cls
.vals
:
1191 code('$val = ${{cls.map[val]}},')
1192 code('Num_$name = ${{len(cls.vals)}}')
1196 if cls
.wrapper_is_struct
:
1197 code(' static const char *${name}Strings[Num_${name}];')
1200 code('extern const char *${name}Strings[Num_${name}];')
1204 code('#endif // $idem_macro')
1206 def cxx_def(cls
, code
):
1207 wrapper_name
= cls
.wrapper_name
1208 file_name
= cls
.__name
__
1209 name
= cls
.__name
__ if cls
.enum_name
is None else cls
.enum_name
1211 code('#include "enums/$file_name.hh"')
1212 if cls
.wrapper_is_struct
:
1213 code('const char *${wrapper_name}::${name}Strings'
1216 code('namespace Enums {')
1218 code(' const char *${name}Strings[Num_${name}] =')
1222 for val
in cls
.vals
:
1227 if not cls
.wrapper_is_struct
:
1228 code('} // namespace $wrapper_name')
1231 def swig_decl(cls
, code
):
1234 %module(package="m5.internal") enum_$name
1237 #include "enums/$name.hh"
1240 %include "enums/$name.hh"
1244 # Base class for enum types.
1245 class Enum(ParamValue
):
1246 __metaclass__
= MetaEnum
1248 cmd_line_settable
= True
1250 # The name of the wrapping namespace or struct
1251 wrapper_name
= 'Enums'
1253 # If true, the enum is wrapped in a struct rather than a namespace
1254 wrapper_is_struct
= False
1256 # If not None, use this as the enum name rather than this class name
1259 def __init__(self
, value
):
1260 if value
not in self
.map:
1261 raise TypeError, "Enum param got bad value '%s' (not in %s)" \
1262 % (value
, self
.vals
)
1265 def __call__(self
, value
):
1266 self
.__init
__(value
)
1270 def cxx_predecls(cls
, code
):
1271 code('#include "enums/$0.hh"', cls
.__name
__)
1274 def swig_predecls(cls
, code
):
1275 code('%import "python/m5/internal/enum_$0.i"', cls
.__name
__)
1278 return int(self
.map[self
.value
])
1283 # how big does a rounding error need to be before we warn about it?
1284 frequency_tolerance
= 0.001 # 0.1%
1286 class TickParamValue(NumericParamValue
):
1289 cmd_line_settable
= True
1292 def cxx_predecls(cls
, code
):
1293 code('#include "base/types.hh"')
1296 def swig_predecls(cls
, code
):
1297 code('%import "stdint.i"')
1298 code('%import "base/types.hh"')
1300 def __call__(self
, value
):
1301 self
.__init
__(value
)
1305 return long(self
.value
)
1307 class Latency(TickParamValue
):
1310 def __init__(self
, value
):
1311 if isinstance(value
, (Latency
, Clock
)):
1312 self
.ticks
= value
.ticks
1313 self
.value
= value
.value
1314 elif isinstance(value
, Frequency
):
1315 self
.ticks
= value
.ticks
1316 self
.value
= 1.0 / value
.value
1317 elif value
.endswith('t'):
1319 self
.value
= int(value
[:-1])
1322 self
.value
= convert
.toLatency(value
)
1324 def __call__(self
, value
):
1325 self
.__init
__(value
)
1328 def __getattr__(self
, attr
):
1329 if attr
in ('latency', 'period'):
1331 if attr
== 'frequency':
1332 return Frequency(self
)
1333 raise AttributeError, "Latency object has no attribute '%s'" % attr
1336 if self
.ticks
or self
.value
== 0:
1339 value
= ticks
.fromSeconds(self
.value
)
1342 # convert latency to ticks
1344 return '%d' % self
.getValue()
1346 class Frequency(TickParamValue
):
1349 def __init__(self
, value
):
1350 if isinstance(value
, (Latency
, Clock
)):
1351 if value
.value
== 0:
1354 self
.value
= 1.0 / value
.value
1355 self
.ticks
= value
.ticks
1356 elif isinstance(value
, Frequency
):
1357 self
.value
= value
.value
1358 self
.ticks
= value
.ticks
1361 self
.value
= convert
.toFrequency(value
)
1363 def __call__(self
, value
):
1364 self
.__init
__(value
)
1367 def __getattr__(self
, attr
):
1368 if attr
== 'frequency':
1370 if attr
in ('latency', 'period'):
1371 return Latency(self
)
1372 raise AttributeError, "Frequency object has no attribute '%s'" % attr
1374 # convert latency to ticks
1376 if self
.ticks
or self
.value
== 0:
1379 value
= ticks
.fromSeconds(1.0 / self
.value
)
1383 return '%d' % self
.getValue()
1385 # A generic Frequency and/or Latency value. Value is stored as a
1386 # latency, just like Latency and Frequency.
1387 class Clock(TickParamValue
):
1388 def __init__(self
, value
):
1389 if isinstance(value
, (Latency
, Clock
)):
1390 self
.ticks
= value
.ticks
1391 self
.value
= value
.value
1392 elif isinstance(value
, Frequency
):
1393 self
.ticks
= value
.ticks
1394 self
.value
= 1.0 / value
.value
1395 elif value
.endswith('t'):
1397 self
.value
= int(value
[:-1])
1400 self
.value
= convert
.anyToLatency(value
)
1402 def __call__(self
, value
):
1403 self
.__init
__(value
)
1407 return "%s" % Latency(self
)
1409 def __getattr__(self
, attr
):
1410 if attr
== 'frequency':
1411 return Frequency(self
)
1412 if attr
in ('latency', 'period'):
1413 return Latency(self
)
1414 raise AttributeError, "Frequency object has no attribute '%s'" % attr
1417 return self
.period
.getValue()
1420 return self
.period
.ini_str()
1422 class Voltage(float,ParamValue
):
1425 cmd_line_settable
= False
1427 def __new__(cls
, value
):
1428 # convert to voltage
1429 val
= convert
.toVoltage(value
)
1430 return super(cls
, Voltage
).__new
__(cls
, val
)
1432 def __call__(self
, value
):
1433 val
= convert
.toVoltage(value
)
1438 return str(self
.getValue())
1445 return '%f' % self
.getValue()
1447 class NetworkBandwidth(float,ParamValue
):
1450 cmd_line_settable
= True
1452 def __new__(cls
, value
):
1453 # convert to bits per second
1454 val
= convert
.toNetworkBandwidth(value
)
1455 return super(cls
, NetworkBandwidth
).__new
__(cls
, val
)
1458 return str(self
.val
)
1460 def __call__(self
, value
):
1461 val
= convert
.toNetworkBandwidth(value
)
1466 # convert to seconds per byte
1467 value
= 8.0 / float(self
)
1468 # convert to ticks per byte
1469 value
= ticks
.fromSeconds(value
)
1473 return '%f' % self
.getValue()
1475 class MemoryBandwidth(float,ParamValue
):
1478 cmd_line_settable
= True
1480 def __new__(cls
, value
):
1481 # convert to bytes per second
1482 val
= convert
.toMemoryBandwidth(value
)
1483 return super(cls
, MemoryBandwidth
).__new
__(cls
, val
)
1485 def __call__(self
, value
):
1486 val
= convert
.toMemoryBandwidth(value
)
1491 # convert to seconds per byte
1494 value
= 1.0 / float(self
)
1495 # convert to ticks per byte
1496 value
= ticks
.fromSeconds(value
)
1500 return '%f' % self
.getValue()
1503 # "Constants"... handy aliases for various values.
1506 # Special class for NULL pointers. Note the special check in
1507 # make_param_value() above that lets these be assigned where a
1508 # SimObject is required.
1509 # only one copy of a particular node
1510 class NullSimObject(object):
1511 __metaclass__
= Singleton
1516 def _instantiate(self
, parent
= None, path
= ''):
1522 def unproxy(self
, base
):
1525 def set_path(self
, parent
, name
):
1534 # The only instance you'll ever need...
1535 NULL
= NullSimObject()
1537 def isNullPointer(value
):
1538 return isinstance(value
, NullSimObject
)
1540 # Some memory range specifications use this as a default upper bound.
1543 AllMemory
= AddrRange(0, MaxAddr
)
1546 #####################################################################
1550 # Ports are used to interconnect objects in the memory system.
1552 #####################################################################
1554 # Port reference: encapsulates a reference to a particular port on a
1555 # particular SimObject.
1556 class PortRef(object):
1557 def __init__(self
, simobj
, name
, role
):
1558 assert(isSimObject(simobj
) or isSimObjectClass(simobj
))
1559 self
.simobj
= simobj
1562 self
.peer
= None # not associated with another port yet
1563 self
.ccConnected
= False # C++ port connection done?
1564 self
.index
= -1 # always -1 for non-vector ports
1567 return '%s.%s' % (self
.simobj
, self
.name
)
1570 # Return the number of connected ports, i.e. 0 is we have no
1571 # peer and 1 if we do.
1572 return int(self
.peer
!= None)
1574 # for config.ini, print peer's name (not ours)
1576 return str(self
.peer
)
1579 def get_config_as_dict(self
):
1580 return {'role' : self
.role
, 'peer' : str(self
.peer
)}
1582 def __getattr__(self
, attr
):
1583 if attr
== 'peerObj':
1584 # shorthand for proxies
1585 return self
.peer
.simobj
1586 raise AttributeError, "'%s' object has no attribute '%s'" % \
1587 (self
.__class
__.__name
__, attr
)
1589 # Full connection is symmetric (both ways). Called via
1590 # SimObject.__setattr__ as a result of a port assignment, e.g.,
1591 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
1592 # e.g., "obj1.portA[3] = obj2.portB".
1593 def connect(self
, other
):
1594 if isinstance(other
, VectorPortRef
):
1595 # reference to plain VectorPort is implicit append
1596 other
= other
._get
_next
()
1597 if self
.peer
and not proxy
.isproxy(self
.peer
):
1598 fatal("Port %s is already connected to %s, cannot connect %s\n",
1599 self
, self
.peer
, other
);
1601 if proxy
.isproxy(other
):
1602 other
.set_param_desc(PortParamDesc())
1603 elif isinstance(other
, PortRef
):
1604 if other
.peer
is not self
:
1608 "assigning non-port reference '%s' to port '%s'" \
1611 def clone(self
, simobj
, memo
):
1612 if memo
.has_key(self
):
1614 newRef
= copy
.copy(self
)
1616 newRef
.simobj
= simobj
1617 assert(isSimObject(newRef
.simobj
))
1618 if self
.peer
and not proxy
.isproxy(self
.peer
):
1619 peerObj
= self
.peer
.simobj(_memo
=memo
)
1620 newRef
.peer
= self
.peer
.clone(peerObj
, memo
)
1621 assert(not isinstance(newRef
.peer
, VectorPortRef
))
1624 def unproxy(self
, simobj
):
1625 assert(simobj
is self
.simobj
)
1626 if proxy
.isproxy(self
.peer
):
1628 realPeer
= self
.peer
.unproxy(self
.simobj
)
1630 print "Error in unproxying port '%s' of %s" % \
1631 (self
.name
, self
.simobj
.path())
1633 self
.connect(realPeer
)
1635 # Call C++ to create corresponding port connection between C++ objects
1636 def ccConnect(self
):
1637 from m5
.internal
.pyobject
import connectPorts
1639 if self
.role
== 'SLAVE':
1640 # do nothing and let the master take care of it
1643 if self
.ccConnected
: # already done this
1646 if not self
.peer
: # nothing to connect to
1649 # check that we connect a master to a slave
1650 if self
.role
== peer
.role
:
1652 "cannot connect '%s' and '%s' due to identical role '%s'" \
1653 % (peer
, self
, self
.role
)
1656 # self is always the master and peer the slave
1657 connectPorts(self
.simobj
.getCCObject(), self
.name
, self
.index
,
1658 peer
.simobj
.getCCObject(), peer
.name
, peer
.index
)
1660 print "Error connecting port %s.%s to %s.%s" % \
1661 (self
.simobj
.path(), self
.name
,
1662 peer
.simobj
.path(), peer
.name
)
1664 self
.ccConnected
= True
1665 peer
.ccConnected
= True
1667 # A reference to an individual element of a VectorPort... much like a
1668 # PortRef, but has an index.
1669 class VectorPortElementRef(PortRef
):
1670 def __init__(self
, simobj
, name
, role
, index
):
1671 PortRef
.__init
__(self
, simobj
, name
, role
)
1675 return '%s.%s[%d]' % (self
.simobj
, self
.name
, self
.index
)
1677 # A reference to a complete vector-valued port (not just a single element).
1678 # Can be indexed to retrieve individual VectorPortElementRef instances.
1679 class VectorPortRef(object):
1680 def __init__(self
, simobj
, name
, role
):
1681 assert(isSimObject(simobj
) or isSimObjectClass(simobj
))
1682 self
.simobj
= simobj
1688 return '%s.%s[:]' % (self
.simobj
, self
.name
)
1691 # Return the number of connected peers, corresponding the the
1692 # length of the elements.
1693 return len(self
.elements
)
1695 # for config.ini, print peer's name (not ours)
1697 return ' '.join([el
.ini_str() for el
in self
.elements
])
1700 def get_config_as_dict(self
):
1701 return {'role' : self
.role
,
1702 'peer' : [el
.ini_str() for el
in self
.elements
]}
1704 def __getitem__(self
, key
):
1705 if not isinstance(key
, int):
1706 raise TypeError, "VectorPort index must be integer"
1707 if key
>= len(self
.elements
):
1708 # need to extend list
1709 ext
= [VectorPortElementRef(self
.simobj
, self
.name
, self
.role
, i
)
1710 for i
in range(len(self
.elements
), key
+1)]
1711 self
.elements
.extend(ext
)
1712 return self
.elements
[key
]
1714 def _get_next(self
):
1715 return self
[len(self
.elements
)]
1717 def __setitem__(self
, key
, value
):
1718 if not isinstance(key
, int):
1719 raise TypeError, "VectorPort index must be integer"
1720 self
[key
].connect(value
)
1722 def connect(self
, other
):
1723 if isinstance(other
, (list, tuple)):
1724 # Assign list of port refs to vector port.
1725 # For now, append them... not sure if that's the right semantics
1726 # or if it should replace the current vector.
1728 self
._get
_next
().connect(ref
)
1730 # scalar assignment to plain VectorPort is implicit append
1731 self
._get
_next
().connect(other
)
1733 def clone(self
, simobj
, memo
):
1734 if memo
.has_key(self
):
1736 newRef
= copy
.copy(self
)
1738 newRef
.simobj
= simobj
1739 assert(isSimObject(newRef
.simobj
))
1740 newRef
.elements
= [el
.clone(simobj
, memo
) for el
in self
.elements
]
1743 def unproxy(self
, simobj
):
1744 [el
.unproxy(simobj
) for el
in self
.elements
]
1746 def ccConnect(self
):
1747 [el
.ccConnect() for el
in self
.elements
]
1749 # Port description object. Like a ParamDesc object, this represents a
1750 # logical port in the SimObject class, not a particular port on a
1751 # SimObject instance. The latter are represented by PortRef objects.
1753 # Generate a PortRef for this port on the given SimObject with the
1755 def makeRef(self
, simobj
):
1756 return PortRef(simobj
, self
.name
, self
.role
)
1758 # Connect an instance of this port (on the given SimObject with
1759 # the given name) with the port described by the supplied PortRef
1760 def connect(self
, simobj
, ref
):
1761 self
.makeRef(simobj
).connect(ref
)
1763 # No need for any pre-declarations at the moment as we merely rely
1764 # on an unsigned int.
1765 def cxx_predecls(self
, code
):
1768 # Declare an unsigned int with the same name as the port, that
1769 # will eventually hold the number of connected ports (and thus the
1770 # number of elements for a VectorPort).
1771 def cxx_decl(self
, code
):
1772 code('unsigned int port_${{self.name}}_connection_count;')
1774 class MasterPort(Port
):
1775 # MasterPort("description")
1776 def __init__(self
, *args
):
1779 self
.role
= 'MASTER'
1781 raise TypeError, 'wrong number of arguments'
1783 class SlavePort(Port
):
1784 # SlavePort("description")
1785 def __init__(self
, *args
):
1790 raise TypeError, 'wrong number of arguments'
1792 # VectorPort description object. Like Port, but represents a vector
1793 # of connections (e.g., as on a Bus).
1794 class VectorPort(Port
):
1795 def __init__(self
, *args
):
1798 def makeRef(self
, simobj
):
1799 return VectorPortRef(simobj
, self
.name
, self
.role
)
1801 class VectorMasterPort(VectorPort
):
1802 # VectorMasterPort("description")
1803 def __init__(self
, *args
):
1806 self
.role
= 'MASTER'
1807 VectorPort
.__init
__(self
, *args
)
1809 raise TypeError, 'wrong number of arguments'
1811 class VectorSlavePort(VectorPort
):
1812 # VectorSlavePort("description")
1813 def __init__(self
, *args
):
1817 VectorPort
.__init
__(self
, *args
)
1819 raise TypeError, 'wrong number of arguments'
1821 # 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
1822 # proxy objects (via set_param_desc()) so that proxy error messages
1824 class PortParamDesc(object):
1825 __metaclass__
= Singleton
1830 baseEnums
= allEnums
.copy()
1831 baseParams
= allParams
.copy()
1834 global allEnums
, allParams
1836 allEnums
= baseEnums
.copy()
1837 allParams
= baseParams
.copy()
1839 __all__
= ['Param', 'VectorParam',
1840 'Enum', 'Bool', 'String', 'Float',
1841 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
1842 'Int32', 'UInt32', 'Int64', 'UInt64',
1843 'Counter', 'Addr', 'Tick', 'Percent',
1844 'TcpPort', 'UdpPort', 'EthernetAddr',
1845 'IpAddress', 'IpNetmask', 'IpWithPort',
1846 'MemorySize', 'MemorySize32',
1847 'Latency', 'Frequency', 'Clock', 'Voltage',
1848 'NetworkBandwidth', 'MemoryBandwidth',
1850 'MaxAddr', 'MaxTick', 'AllMemory',
1852 'NextEthernetAddr', 'NULL',
1853 'MasterPort', 'SlavePort',
1854 'VectorMasterPort', 'VectorSlavePort']