We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
getvalue() in handle.py should configure the returned Binary value
When getting a value from a handle a "BinaryValue()" object is created.  In my case, I tried to slice that value to get the upper bits, but the call failed because the returned value is not configured.

I believe at a minimum, the Handle should set the number of bits, but ideally it would just configure everything the BinaryValue() object needs before returning it.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cocotb/handle.py`
Content:
```
1 #!/usr/bin/env python
2 
3 ''' Copyright (c) 2013 Potential Ventures Ltd
4 Copyright (c) 2013 SolarFlare Communications Inc
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9     * Redistributions of source code must retain the above copyright
10       notice, this list of conditions and the following disclaimer.
11     * Redistributions in binary form must reproduce the above copyright
12       notice, this list of conditions and the following disclaimer in the
13       documentation and/or other materials provided with the distribution.
14     * Neither the name of Potential Ventures Ltd,
15       SolarFlare Communications Inc nor the
16       names of its contributors may be used to endorse or promote products
17       derived from this software without specific prior written permission.
18 
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. '''
29 
30 # -*- coding: utf-8 -*-
31 
32 import logging
33 import ctypes
34 import traceback
35 import sys
36 # from StringIO import StringIO
37 
38 from io import StringIO, BytesIO
39 
40 import os
41 
42 # For autodocumentation don't need the extension modules
43 if "SPHINX_BUILD" in os.environ:
44     simulator = None
45 else:
46     import simulator
47 
48 import cocotb
49 from cocotb.binary import BinaryValue
50 from cocotb.log import SimLog
51 from cocotb.result import TestError
52 from cocotb.triggers import _RisingEdge, _FallingEdge
53 from cocotb.utils import get_python_integer_types
54 
55 
56 class SimHandle(object):
57 
58     def __init__(self, handle):
59         """
60             Args:
61                 _handle [integer] : vpi/vhpi handle to the simulator object
62         """
63         self._handle = handle  # handle used for future simulator transactions
64         self._sub_handles = {}  # Dict. of SimHandle objects created by getattr
65         self._len = None
66 
67         self.name = simulator.get_name_string(self._handle)
68         self.fullname = '%s(%s)' % (self.name,
69                                     simulator.get_type_string(self._handle))
70         self.log = SimLog('cocotb.' + self.name)
71         self.log.debug("Created!")
72         self._r_edge = _RisingEdge(self)
73         self._f_edge = _FallingEdge(self)
74 
75     def __hash__(self):
76         return self._handle
77 
78     def __str__(self):
79         return "%s @0x%x" % (self.name, self._handle)
80 
81     def __getattr__(self, name):
82         """ Query the simulator for a object with the specified name
83             and cache the result to build a tree
84         """
85         # python's builtin dir and IPython's dir2 search for these, 
86         # raise an AttributeError to avoid incorrect calls to _raise_testerror
87         if name in ["__methods__","__members__","trait_names","_getAttributeNames"]:
88             raise AttributeError(name)
89         if name in self._sub_handles:
90             return self._sub_handles[name]
91         new_handle = simulator.get_handle_by_name(self._handle, name)
92         if not new_handle:
93             self._raise_testerror("%s contains no object named %s" %
94                                   (self.name, name))
95         self._sub_handles[name] = SimHandle(new_handle)
96         return self._sub_handles[name]
97 
98     def _raise_testerror(self, msg):
99         lastframe = sys._getframe(2)
100         if sys.version_info[0] >= 3:
101             buff = StringIO()
102             traceback.print_stack(lastframe, file=buff)
103         else:
104             buff_bytes = BytesIO()
105             traceback.print_stack(lastframe, file=buff_bytes)
106             buff = StringIO(buff_bytes.getvalue().decode("UTF8"))
107         self.log.error("%s\n%s" % (msg, buff.getvalue()))
108         exception = TestError(msg)
109         exception.stderr.write(buff.getvalue())
110         buff.close()
111         raise exception
112 
113     def __setattr__(self, name, value):
114         """Provide transparent access to signals"""
115         if (not name.startswith('_') and
116                 not name in ["name", "fullname", "log", "value"] and
117                 self.__hasattr__(name)):
118             getattr(self, name).setcachedvalue(value)
119             return
120         object.__setattr__(self, name, value)
121 
122     def __hasattr__(self, name):
123         """
124         Since calling hasattr(handle, "something") will print out a
125         backtrace to the log since usually attempting to access a
126         non-existent member is an error we provide a 'peek function
127 
128         We still add the found handle to our dictionary to prevent leaking
129         handles.
130         """
131         if name in self._sub_handles:
132             return self._sub_handles[name]
133         new_handle = simulator.get_handle_by_name(self._handle, name)
134         if new_handle:
135             self._sub_handles[name] = SimHandle(new_handle)
136         return new_handle
137 
138     def __getitem__(self, index):
139         if index in self._sub_handles:
140             return self._sub_handles[index]
141         new_handle = simulator.get_handle_by_index(self._handle, index)
142         if not new_handle:
143             self._raise_testerror("%s contains no object at index %d" %
144                                   (self.name, index))
145         self._sub_handles[index] = SimHandle(new_handle)
146         return self._sub_handles[index]
147 
148     def __setitem__(self, index, value):
149         """Provide transparent assignment to bit index"""
150         self.__getitem__(index).setcachedvalue(value)
151 
152     def getvalue(self):
153         result = BinaryValue()
154         result.binstr = self._get_value_str()
155         return result
156 
157     def setimmediatevalue(self, value):
158         """
159         Set the value of the underlying simulation object to value.
160 
161         Args:
162             value (ctypes.Structure, cocotb.binary.BinaryValue, int)
163                 The value to drive onto the simulator object
164 
165         Raises:
166             TypeError
167 
168         This operation will fail unless the handle refers to a modifiable
169         object eg net, signal or variable.
170 
171         We determine the library call to make based on the type of the value
172 
173         Assigning integers less than 32-bits is faster
174         """
175         if (isinstance(value, get_python_integer_types()) and
176                 value < 0x7fffffff):
177             simulator.set_signal_val(self._handle, value)
178             return
179 
180         if isinstance(value, ctypes.Structure):
181             value = BinaryValue(value=cocotb.utils.pack(value), bits=len(self))
182         elif isinstance(value, get_python_integer_types()):
183             value = BinaryValue(value=value, bits=len(self), bigEndian=False)
184         elif not isinstance(value, BinaryValue):
185             self.log.critical("Unsupported type for value assignment: %s (%s)"
186                               % (type(value), repr(value)))
187             raise TypeError("Unable to set simulator value with type %s" %
188                             (type(value)))
189 
190         simulator.set_signal_val_str(self._handle, value.binstr)
191 
192     def setcachedvalue(self, value):
193         """Intercept the store of a value and hold in cache.
194 
195         This operation is to enable all of the scheduled callbacks to completed
196         with the same read data and for the writes to occour on the next
197         sim time"""
198         cocotb.scheduler.save_write(self, value)
199 
200     # We want to maintain compatability with python 2.5 so we can't use
201     # @property with a setter
202     value = property(getvalue, setcachedvalue, None,
203                      "A reference to the value")
204 
205     def _get_value_str(self):
206         return simulator.get_signal_val(self._handle)
207 
208     def __le__(self, value):
209         """Overload the less than or equal to operator to
210             provide an hdl-like shortcut
211                 module.signal <= 2
212         """
213         self.value = value
214 
215     def __len__(self):
216         """Returns the 'length' of the underlying object.
217 
218         For vectors this is the number of bits.
219 
220         TODO: Handle other types (loops, generate etc)
221         """
222         if self._len is None:
223             self._len = len(self._get_value_str())
224         return self._len
225 
226     def __cmp__(self, other):
227 
228         # Permits comparison of handles i.e. if clk == dut.clk
229         if isinstance(other, SimHandle):
230             if self._handle == other._handle:
231                 return 0
232             return 1
233 
234         # Use the comparison method of the other object against our value
235         return self.value.__cmp__(other)
236 
237     def __iter__(self):
238         """Iterates over all known types defined by simulator module"""
239         for handle_type in [simulator.MODULE,
240                             simulator.PARAMETER,
241                             simulator.REG,
242                             simulator.NET,
243                             simulator.NETARRAY]:
244             iterator = simulator.iterate(handle_type, self._handle)
245             while True:
246                 try:
247                     thing = simulator.next(iterator)
248                 except StopIteration:
249                     break
250                 hdl = SimHandle(thing)
251                 self._sub_handles[hdl.name] = hdl
252                 yield hdl
253 
254     def __int__(self):
255         return int(self.value)
256
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cocotb/handle.py b/cocotb/handle.py
--- a/cocotb/handle.py
+++ b/cocotb/handle.py
@@ -82,7 +82,7 @@
         """ Query the simulator for a object with the specified name
             and cache the result to build a tree
         """
-        # python's builtin dir and IPython's dir2 search for these, 
+        # python's builtin dir and IPython's dir2 search for these,
         # raise an AttributeError to avoid incorrect calls to _raise_testerror
         if name in ["__methods__","__members__","trait_names","_getAttributeNames"]:
             raise AttributeError(name)
@@ -150,7 +150,7 @@
         self.__getitem__(index).setcachedvalue(value)
 
     def getvalue(self):
-        result = BinaryValue()
+        result = BinaryValue(bits=len(self))
         result.binstr = self._get_value_str()
         return result

{"golden_diff": "diff --git a/cocotb/handle.py b/cocotb/handle.py\n--- a/cocotb/handle.py\n+++ b/cocotb/handle.py\n@@ -82,7 +82,7 @@\n         \"\"\" Query the simulator for a object with the specified name\n             and cache the result to build a tree\n         \"\"\"\n-        # python's builtin dir and IPython's dir2 search for these, \n+        # python's builtin dir and IPython's dir2 search for these,\n         # raise an AttributeError to avoid incorrect calls to _raise_testerror\n         if name in [\"__methods__\",\"__members__\",\"trait_names\",\"_getAttributeNames\"]:\n             raise AttributeError(name)\n@@ -150,7 +150,7 @@\n         self.__getitem__(index).setcachedvalue(value)\n \n     def getvalue(self):\n-        result = BinaryValue()\n+        result = BinaryValue(bits=len(self))\n         result.binstr = self._get_value_str()\n         return result\n", "issue": "getvalue() in handle.py should configure the returned Binary value\nWhen getting a value from a handle a \"BinaryValue()\" object is created.  In my case, I tried to slice that value to get the upper bits, but the call failed because the returned value is not configured.\n\nI believe at a minimum, the Handle should set the number of bits, but ideally it would just configure everything the BinaryValue() object needs before returning it.\n\n", "before_files": [{"content": "#!/usr/bin/env python\n\n''' Copyright (c) 2013 Potential Ventures Ltd\nCopyright (c) 2013 SolarFlare Communications Inc\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of Potential Ventures Ltd,\n      SolarFlare Communications Inc nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. '''\n\n# -*- coding: utf-8 -*-\n\nimport logging\nimport ctypes\nimport traceback\nimport sys\n# from StringIO import StringIO\n\nfrom io import StringIO, BytesIO\n\nimport os\n\n# For autodocumentation don't need the extension modules\nif \"SPHINX_BUILD\" in os.environ:\n    simulator = None\nelse:\n    import simulator\n\nimport cocotb\nfrom cocotb.binary import BinaryValue\nfrom cocotb.log import SimLog\nfrom cocotb.result import TestError\nfrom cocotb.triggers import _RisingEdge, _FallingEdge\nfrom cocotb.utils import get_python_integer_types\n\n\nclass SimHandle(object):\n\n    def __init__(self, handle):\n        \"\"\"\n            Args:\n                _handle [integer] : vpi/vhpi handle to the simulator object\n        \"\"\"\n        self._handle = handle  # handle used for future simulator transactions\n        self._sub_handles = {}  # Dict. of SimHandle objects created by getattr\n        self._len = None\n\n        self.name = simulator.get_name_string(self._handle)\n        self.fullname = '%s(%s)' % (self.name,\n                                    simulator.get_type_string(self._handle))\n        self.log = SimLog('cocotb.' + self.name)\n        self.log.debug(\"Created!\")\n        self._r_edge = _RisingEdge(self)\n        self._f_edge = _FallingEdge(self)\n\n    def __hash__(self):\n        return self._handle\n\n    def __str__(self):\n        return \"%s @0x%x\" % (self.name, self._handle)\n\n    def __getattr__(self, name):\n        \"\"\" Query the simulator for a object with the specified name\n            and cache the result to build a tree\n        \"\"\"\n        # python's builtin dir and IPython's dir2 search for these, \n        # raise an AttributeError to avoid incorrect calls to _raise_testerror\n        if name in [\"__methods__\",\"__members__\",\"trait_names\",\"_getAttributeNames\"]:\n            raise AttributeError(name)\n        if name in self._sub_handles:\n            return self._sub_handles[name]\n        new_handle = simulator.get_handle_by_name(self._handle, name)\n        if not new_handle:\n            self._raise_testerror(\"%s contains no object named %s\" %\n                                  (self.name, name))\n        self._sub_handles[name] = SimHandle(new_handle)\n        return self._sub_handles[name]\n\n    def _raise_testerror(self, msg):\n        lastframe = sys._getframe(2)\n        if sys.version_info[0] >= 3:\n            buff = StringIO()\n            traceback.print_stack(lastframe, file=buff)\n        else:\n            buff_bytes = BytesIO()\n            traceback.print_stack(lastframe, file=buff_bytes)\n            buff = StringIO(buff_bytes.getvalue().decode(\"UTF8\"))\n        self.log.error(\"%s\\n%s\" % (msg, buff.getvalue()))\n        exception = TestError(msg)\n        exception.stderr.write(buff.getvalue())\n        buff.close()\n        raise exception\n\n    def __setattr__(self, name, value):\n        \"\"\"Provide transparent access to signals\"\"\"\n        if (not name.startswith('_') and\n                not name in [\"name\", \"fullname\", \"log\", \"value\"] and\n                self.__hasattr__(name)):\n            getattr(self, name).setcachedvalue(value)\n            return\n        object.__setattr__(self, name, value)\n\n    def __hasattr__(self, name):\n        \"\"\"\n        Since calling hasattr(handle, \"something\") will print out a\n        backtrace to the log since usually attempting to access a\n        non-existent member is an error we provide a 'peek function\n\n        We still add the found handle to our dictionary to prevent leaking\n        handles.\n        \"\"\"\n        if name in self._sub_handles:\n            return self._sub_handles[name]\n        new_handle = simulator.get_handle_by_name(self._handle, name)\n        if new_handle:\n            self._sub_handles[name] = SimHandle(new_handle)\n        return new_handle\n\n    def __getitem__(self, index):\n        if index in self._sub_handles:\n            return self._sub_handles[index]\n        new_handle = simulator.get_handle_by_index(self._handle, index)\n        if not new_handle:\n            self._raise_testerror(\"%s contains no object at index %d\" %\n                                  (self.name, index))\n        self._sub_handles[index] = SimHandle(new_handle)\n        return self._sub_handles[index]\n\n    def __setitem__(self, index, value):\n        \"\"\"Provide transparent assignment to bit index\"\"\"\n        self.__getitem__(index).setcachedvalue(value)\n\n    def getvalue(self):\n        result = BinaryValue()\n        result.binstr = self._get_value_str()\n        return result\n\n    def setimmediatevalue(self, value):\n        \"\"\"\n        Set the value of the underlying simulation object to value.\n\n        Args:\n            value (ctypes.Structure, cocotb.binary.BinaryValue, int)\n                The value to drive onto the simulator object\n\n        Raises:\n            TypeError\n\n        This operation will fail unless the handle refers to a modifiable\n        object eg net, signal or variable.\n\n        We determine the library call to make based on the type of the value\n\n        Assigning integers less than 32-bits is faster\n        \"\"\"\n        if (isinstance(value, get_python_integer_types()) and\n                value < 0x7fffffff):\n            simulator.set_signal_val(self._handle, value)\n            return\n\n        if isinstance(value, ctypes.Structure):\n            value = BinaryValue(value=cocotb.utils.pack(value), bits=len(self))\n        elif isinstance(value, get_python_integer_types()):\n            value = BinaryValue(value=value, bits=len(self), bigEndian=False)\n        elif not isinstance(value, BinaryValue):\n            self.log.critical(\"Unsupported type for value assignment: %s (%s)\"\n                              % (type(value), repr(value)))\n            raise TypeError(\"Unable to set simulator value with type %s\" %\n                            (type(value)))\n\n        simulator.set_signal_val_str(self._handle, value.binstr)\n\n    def setcachedvalue(self, value):\n        \"\"\"Intercept the store of a value and hold in cache.\n\n        This operation is to enable all of the scheduled callbacks to completed\n        with the same read data and for the writes to occour on the next\n        sim time\"\"\"\n        cocotb.scheduler.save_write(self, value)\n\n    # We want to maintain compatability with python 2.5 so we can't use\n    # @property with a setter\n    value = property(getvalue, setcachedvalue, None,\n                     \"A reference to the value\")\n\n    def _get_value_str(self):\n        return simulator.get_signal_val(self._handle)\n\n    def __le__(self, value):\n        \"\"\"Overload the less than or equal to operator to\n            provide an hdl-like shortcut\n                module.signal <= 2\n        \"\"\"\n        self.value = value\n\n    def __len__(self):\n        \"\"\"Returns the 'length' of the underlying object.\n\n        For vectors this is the number of bits.\n\n        TODO: Handle other types (loops, generate etc)\n        \"\"\"\n        if self._len is None:\n            self._len = len(self._get_value_str())\n        return self._len\n\n    def __cmp__(self, other):\n\n        # Permits comparison of handles i.e. if clk == dut.clk\n        if isinstance(other, SimHandle):\n            if self._handle == other._handle:\n                return 0\n            return 1\n\n        # Use the comparison method of the other object against our value\n        return self.value.__cmp__(other)\n\n    def __iter__(self):\n        \"\"\"Iterates over all known types defined by simulator module\"\"\"\n        for handle_type in [simulator.MODULE,\n                            simulator.PARAMETER,\n                            simulator.REG,\n                            simulator.NET,\n                            simulator.NETARRAY]:\n            iterator = simulator.iterate(handle_type, self._handle)\n            while True:\n                try:\n                    thing = simulator.next(iterator)\n                except StopIteration:\n                    break\n                hdl = SimHandle(thing)\n                self._sub_handles[hdl.name] = hdl\n                yield hdl\n\n    def __int__(self):\n        return int(self.value)\n", "path": "cocotb/handle.py"}], "after_files": [{"content": "#!/usr/bin/env python\n\n''' Copyright (c) 2013 Potential Ventures Ltd\nCopyright (c) 2013 SolarFlare Communications Inc\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of Potential Ventures Ltd,\n      SolarFlare Communications Inc nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. '''\n\n# -*- coding: utf-8 -*-\n\nimport logging\nimport ctypes\nimport traceback\nimport sys\n# from StringIO import StringIO\n\nfrom io import StringIO, BytesIO\n\nimport os\n\n# For autodocumentation don't need the extension modules\nif \"SPHINX_BUILD\" in os.environ:\n    simulator = None\nelse:\n    import simulator\n\nimport cocotb\nfrom cocotb.binary import BinaryValue\nfrom cocotb.log import SimLog\nfrom cocotb.result import TestError\nfrom cocotb.triggers import _RisingEdge, _FallingEdge\nfrom cocotb.utils import get_python_integer_types\n\n\nclass SimHandle(object):\n\n    def __init__(self, handle):\n        \"\"\"\n            Args:\n                _handle [integer] : vpi/vhpi handle to the simulator object\n        \"\"\"\n        self._handle = handle  # handle used for future simulator transactions\n        self._sub_handles = {}  # Dict. of SimHandle objects created by getattr\n        self._len = None\n\n        self.name = simulator.get_name_string(self._handle)\n        self.fullname = '%s(%s)' % (self.name,\n                                    simulator.get_type_string(self._handle))\n        self.log = SimLog('cocotb.' + self.name)\n        self.log.debug(\"Created!\")\n        self._r_edge = _RisingEdge(self)\n        self._f_edge = _FallingEdge(self)\n\n    def __hash__(self):\n        return self._handle\n\n    def __str__(self):\n        return \"%s @0x%x\" % (self.name, self._handle)\n\n    def __getattr__(self, name):\n        \"\"\" Query the simulator for a object with the specified name\n            and cache the result to build a tree\n        \"\"\"\n        # python's builtin dir and IPython's dir2 search for these,\n        # raise an AttributeError to avoid incorrect calls to _raise_testerror\n        if name in [\"__methods__\",\"__members__\",\"trait_names\",\"_getAttributeNames\"]:\n            raise AttributeError(name)\n        if name in self._sub_handles:\n            return self._sub_handles[name]\n        new_handle = simulator.get_handle_by_name(self._handle, name)\n        if not new_handle:\n            self._raise_testerror(\"%s contains no object named %s\" %\n                                  (self.name, name))\n        self._sub_handles[name] = SimHandle(new_handle)\n        return self._sub_handles[name]\n\n    def _raise_testerror(self, msg):\n        lastframe = sys._getframe(2)\n        if sys.version_info[0] >= 3:\n            buff = StringIO()\n            traceback.print_stack(lastframe, file=buff)\n        else:\n            buff_bytes = BytesIO()\n            traceback.print_stack(lastframe, file=buff_bytes)\n            buff = StringIO(buff_bytes.getvalue().decode(\"UTF8\"))\n        self.log.error(\"%s\\n%s\" % (msg, buff.getvalue()))\n        exception = TestError(msg)\n        exception.stderr.write(buff.getvalue())\n        buff.close()\n        raise exception\n\n    def __setattr__(self, name, value):\n        \"\"\"Provide transparent access to signals\"\"\"\n        if (not name.startswith('_') and\n                not name in [\"name\", \"fullname\", \"log\", \"value\"] and\n                self.__hasattr__(name)):\n            getattr(self, name).setcachedvalue(value)\n            return\n        object.__setattr__(self, name, value)\n\n    def __hasattr__(self, name):\n        \"\"\"\n        Since calling hasattr(handle, \"something\") will print out a\n        backtrace to the log since usually attempting to access a\n        non-existent member is an error we provide a 'peek function\n\n        We still add the found handle to our dictionary to prevent leaking\n        handles.\n        \"\"\"\n        if name in self._sub_handles:\n            return self._sub_handles[name]\n        new_handle = simulator.get_handle_by_name(self._handle, name)\n        if new_handle:\n            self._sub_handles[name] = SimHandle(new_handle)\n        return new_handle\n\n    def __getitem__(self, index):\n        if index in self._sub_handles:\n            return self._sub_handles[index]\n        new_handle = simulator.get_handle_by_index(self._handle, index)\n        if not new_handle:\n            self._raise_testerror(\"%s contains no object at index %d\" %\n                                  (self.name, index))\n        self._sub_handles[index] = SimHandle(new_handle)\n        return self._sub_handles[index]\n\n    def __setitem__(self, index, value):\n        \"\"\"Provide transparent assignment to bit index\"\"\"\n        self.__getitem__(index).setcachedvalue(value)\n\n    def getvalue(self):\n        result = BinaryValue(bits=len(self))\n        result.binstr = self._get_value_str()\n        return result\n\n    def setimmediatevalue(self, value):\n        \"\"\"\n        Set the value of the underlying simulation object to value.\n\n        Args:\n            value (ctypes.Structure, cocotb.binary.BinaryValue, int)\n                The value to drive onto the simulator object\n\n        Raises:\n            TypeError\n\n        This operation will fail unless the handle refers to a modifiable\n        object eg net, signal or variable.\n\n        We determine the library call to make based on the type of the value\n\n        Assigning integers less than 32-bits is faster\n        \"\"\"\n        if (isinstance(value, get_python_integer_types()) and\n                value < 0x7fffffff):\n            simulator.set_signal_val(self._handle, value)\n            return\n\n        if isinstance(value, ctypes.Structure):\n            value = BinaryValue(value=cocotb.utils.pack(value), bits=len(self))\n        elif isinstance(value, get_python_integer_types()):\n            value = BinaryValue(value=value, bits=len(self), bigEndian=False)\n        elif not isinstance(value, BinaryValue):\n            self.log.critical(\"Unsupported type for value assignment: %s (%s)\"\n                              % (type(value), repr(value)))\n            raise TypeError(\"Unable to set simulator value with type %s\" %\n                            (type(value)))\n\n        simulator.set_signal_val_str(self._handle, value.binstr)\n\n    def setcachedvalue(self, value):\n        \"\"\"Intercept the store of a value and hold in cache.\n\n        This operation is to enable all of the scheduled callbacks to completed\n        with the same read data and for the writes to occour on the next\n        sim time\"\"\"\n        cocotb.scheduler.save_write(self, value)\n\n    # We want to maintain compatability with python 2.5 so we can't use\n    # @property with a setter\n    value = property(getvalue, setcachedvalue, None,\n                     \"A reference to the value\")\n\n    def _get_value_str(self):\n        return simulator.get_signal_val(self._handle)\n\n    def __le__(self, value):\n        \"\"\"Overload the less than or equal to operator to\n            provide an hdl-like shortcut\n                module.signal <= 2\n        \"\"\"\n        self.value = value\n\n    def __len__(self):\n        \"\"\"Returns the 'length' of the underlying object.\n\n        For vectors this is the number of bits.\n\n        TODO: Handle other types (loops, generate etc)\n        \"\"\"\n        if self._len is None:\n            self._len = len(self._get_value_str())\n        return self._len\n\n    def __cmp__(self, other):\n\n        # Permits comparison of handles i.e. if clk == dut.clk\n        if isinstance(other, SimHandle):\n            if self._handle == other._handle:\n                return 0\n            return 1\n\n        # Use the comparison method of the other object against our value\n        return self.value.__cmp__(other)\n\n    def __iter__(self):\n        \"\"\"Iterates over all known types defined by simulator module\"\"\"\n        for handle_type in [simulator.MODULE,\n                            simulator.PARAMETER,\n                            simulator.REG,\n                            simulator.NET,\n                            simulator.NETARRAY]:\n            iterator = simulator.iterate(handle_type, self._handle)\n            while True:\n                try:\n                    thing = simulator.next(iterator)\n                except StopIteration:\n                    break\n                hdl = SimHandle(thing)\n                self._sub_handles[hdl.name] = hdl\n                yield hdl\n\n    def __int__(self):\n        return int(self.value)\n", "path": "cocotb/handle.py"}]}