We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TOPLEVEL should be whitespace stripped
From here: https://github.com/cocotb/cocotb/blob/ecb43878a6af0605fdf08c2f1829cc401bfdeb36/cocotb/__init__.py#L219-L225

On Questa with the FLI, trailing whitespace causes the toplevel entity to not be found since it does a strict `!strcmp()`.

--- 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/__init__.py`
Content:
```
1 # Copyright (c) 2013 Potential Ventures Ltd
2 # Copyright (c) 2013 SolarFlare Communications Inc
3 # All rights reserved.
4 
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are met:
7 #     * Redistributions of source code must retain the above copyright
8 #       notice, this list of conditions and the following disclaimer.
9 #     * Redistributions in binary form must reproduce the above copyright
10 #       notice, this list of conditions and the following disclaimer in the
11 #       documentation and/or other materials provided with the distribution.
12 #     * Neither the name of Potential Ventures Ltd,
13 #       SolarFlare Communications Inc nor the
14 #       names of its contributors may be used to endorse or promote products
15 #       derived from this software without specific prior written permission.
16 
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 # DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY
21 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 """
29 Cocotb is a coroutine, cosimulation framework for writing testbenches in Python.
30 
31 See https://docs.cocotb.org for full documentation
32 """
33 import os
34 import sys
35 import logging
36 import threading
37 import random
38 import time
39 import warnings
40 from typing import Dict, List, Optional, Union
41 from collections.abc import Coroutine
42 
43 import cocotb.handle
44 import cocotb.log
45 from cocotb.scheduler import Scheduler
46 from cocotb.regression import RegressionManager
47 from cocotb.decorators import RunningTask
48 
49 # Things we want in the cocotb namespace
50 from cocotb.decorators import test, coroutine, hook, function, external  # noqa: F401
51 
52 from ._version import __version__
53 
54 
55 def _setup_logging():
56     global log
57 
58     def _reopen_stream_with_buffering(stream_name):
59         try:
60             if not getattr(sys, stream_name).isatty():
61                 setattr(sys, stream_name, os.fdopen(getattr(sys, stream_name).fileno(), 'w', 1))
62                 return True
63             return False
64         except Exception as e:
65             return e
66 
67     # If stdout/stderr are not TTYs, Python may not have opened them with line
68     # buffering. In that case, try to reopen them with line buffering
69     # explicitly enabled. This ensures that prints such as stack traces always
70     # appear. Continue silently if this fails.
71     _stdout_buffer_result = _reopen_stream_with_buffering('stdout')
72     _stderr_buffer_result = _reopen_stream_with_buffering('stderr')
73 
74     # Don't set the logging up until we've attempted to fix the standard IO,
75     # otherwise it will end up connected to the unfixed IO.
76     cocotb.log.default_config()
77     log = logging.getLogger(__name__)
78 
79     # we can't log these things until the logging is set up!
80     if _stderr_buffer_result is True:
81         log.debug("Reopened stderr with line buffering")
82     if _stdout_buffer_result is True:
83         log.debug("Reopened stdout with line buffering")
84     if isinstance(_stdout_buffer_result, Exception) or isinstance(_stderr_buffer_result, Exception):
85         if isinstance(_stdout_buffer_result, Exception):
86             log.warning("Failed to ensure that stdout is line buffered", exc_info=_stdout_buffer_result)
87         if isinstance(_stderr_buffer_result, Exception):
88             log.warning("Failed to ensure that stderr is line buffered", exc_info=_stderr_buffer_result)
89         log.warning("Some stack traces may not appear because of this.")
90 
91     del _stderr_buffer_result, _stdout_buffer_result
92 
93 
94 # Singleton scheduler instance
95 # NB this cheekily ensures a singleton since we're replacing the reference
96 # so that cocotb.scheduler gives you the singleton instance and not the
97 # scheduler package
98 
99 scheduler: Optional[Scheduler] = None
100 """The global scheduler instance.
101 
102 This is guaranteed to hold a value at test time.
103 """
104 
105 regression_manager: Optional[RegressionManager] = None
106 """The global regression manager instance.
107 
108 This is guaranteed to hold a value at test time.
109 """
110 
111 argv: Optional[List[str]] = None
112 """The argument list as seen by the simulator.
113 
114 This is guaranteed to hold a value at test time.
115 """
116 
117 argc: Optional[int] = None
118 """The length of :data:`cocotb.argv`.
119 
120 This is guaranteed to hold a value at test time.
121 """
122 
123 plusargs: Optional[Dict[str, Union[bool, str]]] = None
124 """A dictionary of "plusargs" handed to the simulation.
125 
126 See :make:var:`PLUSARGS` for details.
127 This is guaranteed to hold a value at test time.
128 """
129 
130 LANGUAGE: Optional[str] = os.getenv("TOPLEVEL_LANG")
131 """The value of :make:var:`TOPLEVEL_LANG`.
132 
133 This is guaranteed to hold a value at test time.
134 """
135 
136 SIM_NAME: Optional[str] = None
137 """The running simulator product information.
138 
139 ``None`` if :mod:`cocotb` was not loaded from a simulator.
140 """
141 
142 SIM_VERSION: Optional[str] = None
143 """The version of the running simulator.
144 
145 ``None`` if :mod:`cocotb` was not loaded from a simulator."""
146 
147 RANDOM_SEED: Optional[int] = None
148 """
149 The value passed to the Python default random number generator.
150 
151 See :envvar:`RANDOM_SEED` for details on how the value is computed.
152 This is guaranteed to hold a value at test time.
153 """
154 
155 _library_coverage = None
156 """ used for cocotb library coverage """
157 
158 top: Optional[cocotb.handle.SimHandleBase] = None
159 r"""
160 A handle to the :envvar:`TOPLEVEL` entity/module.
161 
162 This is equivalent to the :term:`DUT` parameter given to cocotb tests, so it can be used wherever that variable can be used.
163 It is particularly useful for extracting information about the :term:`DUT` in module-level class and function definitions;
164 and in parameters to :class:`.TestFactory`\ s.
165 ``None`` if :mod:`cocotb` was not loaded from a simulator.
166 """
167 
168 
169 def fork(coro: Union[RunningTask, Coroutine]) -> RunningTask:
170     """ Schedule a coroutine to be run concurrently. See :ref:`coroutines` for details on its use. """
171     return scheduler.add(coro)
172 
173 
174 # FIXME is this really required?
175 _rlock = threading.RLock()
176 
177 
178 def mem_debug(port):
179     import cocotb.memdebug
180     cocotb.memdebug.start(port)
181 
182 
183 def _initialise_testbench(argv_):  # pragma: no cover
184     """Initialize testbench.
185 
186     This function is called after the simulator has elaborated all
187     entities and is ready to run the test.
188 
189     The test must be defined by the environment variables
190     :envvar:`MODULE` and :envvar:`TESTCASE`.
191 
192     The environment variable :envvar:`COCOTB_HOOKS`, if present, contains a
193     comma-separated list of modules to be executed before the first test.
194     """
195     with _rlock:
196 
197         if "COCOTB_LIBRARY_COVERAGE" in os.environ:
198             import coverage
199 
200             global _library_coverage
201             _library_coverage = coverage.coverage(
202                 data_file=".coverage.cocotb",
203                 branch=True,
204                 include=["{}/*".format(os.path.dirname(__file__))])
205             _library_coverage.start()
206 
207         return _initialise_testbench_(argv_)
208 
209 
210 def _initialise_testbench_(argv_):
211     # The body of this function is split in two because no coverage is collected on
212     # the function that starts the coverage. By splitting it in two we get coverage
213     # on most of the function.
214 
215     global argc, argv
216     argv = argv_
217     argc = len(argv)
218 
219     root_name = os.getenv("TOPLEVEL")
220     if root_name is not None:
221         if root_name == "":
222             root_name = None
223         elif '.' in root_name:
224             # Skip any library component of the toplevel
225             root_name = root_name.split(".", 1)[1]
226 
227     # sys.path normally includes "" (the current directory), but does not appear to when python is embedded.
228     # Add it back because users expect to be able to import files in their test directory.
229     # TODO: move this to gpi_embed.cpp
230     sys.path.insert(0, "")
231 
232     _setup_logging()
233 
234     # From https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners
235     # If the user doesn't want to see these, they can always change the global
236     # warning settings in their test module.
237     if not sys.warnoptions:
238         warnings.simplefilter("default")
239 
240     from cocotb import simulator
241 
242     global SIM_NAME, SIM_VERSION
243     SIM_NAME = simulator.get_simulator_product().strip()
244     SIM_VERSION = simulator.get_simulator_version().strip()
245 
246     cocotb.log.info("Running on {} version {}".format(SIM_NAME, SIM_VERSION))
247 
248     memcheck_port = os.getenv('MEMCHECK')
249     if memcheck_port is not None:
250         mem_debug(int(memcheck_port))
251 
252     log.info("Running tests with cocotb v%s from %s" %
253              (__version__, os.path.dirname(__file__)))
254 
255     # Create the base handle type
256 
257     process_plusargs()
258 
259     global scheduler
260     scheduler = Scheduler()
261 
262     # Seed the Python random number generator to make this repeatable
263     global RANDOM_SEED
264     RANDOM_SEED = os.getenv('RANDOM_SEED')
265 
266     if RANDOM_SEED is None:
267         if 'ntb_random_seed' in plusargs:
268             RANDOM_SEED = eval(plusargs['ntb_random_seed'])
269         elif 'seed' in plusargs:
270             RANDOM_SEED = eval(plusargs['seed'])
271         else:
272             RANDOM_SEED = int(time.time())
273         log.info("Seeding Python random module with %d" % (RANDOM_SEED))
274     else:
275         RANDOM_SEED = int(RANDOM_SEED)
276         log.info("Seeding Python random module with supplied seed %d" % (RANDOM_SEED))
277     random.seed(RANDOM_SEED)
278 
279     # Setup DUT object
280     from cocotb import simulator
281 
282     handle = simulator.get_root_handle(root_name)
283     if not handle:
284         raise RuntimeError("Can not find root handle ({})".format(root_name))
285 
286     global top
287     top = cocotb.handle.SimHandle(handle)
288 
289     try:
290         import pytest
291     except ImportError:
292         log.warning("Pytest not found, assertion rewriting will not occur")
293     else:
294         try:
295             # Install the assertion rewriting hook, which must be done before we
296             # import the test modules.
297             from _pytest.config import Config
298             from _pytest.assertion import install_importhook
299             pytest_conf = Config.fromdictargs([], {})
300             install_importhook(pytest_conf)
301         except Exception:
302             log.exception(
303                 "Configuring the assertion rewrite hook using pytest {} failed. "
304                 "Please file a bug report!".format(pytest.__version__))
305 
306     # start Regression Manager
307     global regression_manager
308     regression_manager = RegressionManager.from_discovery(top)
309     regression_manager.execute()
310 
311     return True
312 
313 
314 def _sim_event(level, message):
315     """Function that can be called externally to signal an event."""
316     # SIM_INFO = 0
317     SIM_TEST_FAIL = 1
318     SIM_FAIL = 2
319     from cocotb.result import TestFailure, SimFailure
320 
321     if level is SIM_TEST_FAIL:
322         scheduler.log.error("Failing test at simulator request")
323         scheduler._finish_test(TestFailure("Failure from external source: {}".format(message)))
324     elif level is SIM_FAIL:
325         # We simply return here as the simulator will exit
326         # so no cleanup is needed
327         msg = "Failing test at simulator request before test run completion: {}".format(message)
328         scheduler.log.error(msg)
329         scheduler._finish_scheduler(SimFailure(msg))
330     else:
331         scheduler.log.error("Unsupported sim event")
332 
333     return True
334 
335 
336 def process_plusargs():
337 
338     global plusargs
339 
340     plusargs = {}
341 
342     for option in cocotb.argv:
343         if option.startswith('+'):
344             if option.find('=') != -1:
345                 (name, value) = option[1:].split('=')
346                 plusargs[name] = value
347             else:
348                 plusargs[option[1:]] = True
349
```
--- 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/__init__.py b/cocotb/__init__.py
--- a/cocotb/__init__.py
+++ b/cocotb/__init__.py
@@ -218,6 +218,7 @@
 
     root_name = os.getenv("TOPLEVEL")
     if root_name is not None:
+        root_name = root_name.strip()
         if root_name == "":
             root_name = None
         elif '.' in root_name:

{"golden_diff": "diff --git a/cocotb/__init__.py b/cocotb/__init__.py\n--- a/cocotb/__init__.py\n+++ b/cocotb/__init__.py\n@@ -218,6 +218,7 @@\n \n     root_name = os.getenv(\"TOPLEVEL\")\n     if root_name is not None:\n+        root_name = root_name.strip()\n         if root_name == \"\":\n             root_name = None\n         elif '.' in root_name:\n", "issue": "TOPLEVEL should be whitespace stripped\nFrom here: https://github.com/cocotb/cocotb/blob/ecb43878a6af0605fdf08c2f1829cc401bfdeb36/cocotb/__init__.py#L219-L225\r\n\r\nOn Questa with the FLI, trailing whitespace causes the toplevel entity to not be found since it does a strict `!strcmp()`.\n", "before_files": [{"content": "# Copyright (c) 2013 Potential Ventures Ltd\n# Copyright (c) 2013 SolarFlare Communications Inc\n# All rights reserved.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, 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\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY\n# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# ON 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\n# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\"\"\"\nCocotb is a coroutine, cosimulation framework for writing testbenches in Python.\n\nSee https://docs.cocotb.org for full documentation\n\"\"\"\nimport os\nimport sys\nimport logging\nimport threading\nimport random\nimport time\nimport warnings\nfrom typing import Dict, List, Optional, Union\nfrom collections.abc import Coroutine\n\nimport cocotb.handle\nimport cocotb.log\nfrom cocotb.scheduler import Scheduler\nfrom cocotb.regression import RegressionManager\nfrom cocotb.decorators import RunningTask\n\n# Things we want in the cocotb namespace\nfrom cocotb.decorators import test, coroutine, hook, function, external  # noqa: F401\n\nfrom ._version import __version__\n\n\ndef _setup_logging():\n    global log\n\n    def _reopen_stream_with_buffering(stream_name):\n        try:\n            if not getattr(sys, stream_name).isatty():\n                setattr(sys, stream_name, os.fdopen(getattr(sys, stream_name).fileno(), 'w', 1))\n                return True\n            return False\n        except Exception as e:\n            return e\n\n    # If stdout/stderr are not TTYs, Python may not have opened them with line\n    # buffering. In that case, try to reopen them with line buffering\n    # explicitly enabled. This ensures that prints such as stack traces always\n    # appear. Continue silently if this fails.\n    _stdout_buffer_result = _reopen_stream_with_buffering('stdout')\n    _stderr_buffer_result = _reopen_stream_with_buffering('stderr')\n\n    # Don't set the logging up until we've attempted to fix the standard IO,\n    # otherwise it will end up connected to the unfixed IO.\n    cocotb.log.default_config()\n    log = logging.getLogger(__name__)\n\n    # we can't log these things until the logging is set up!\n    if _stderr_buffer_result is True:\n        log.debug(\"Reopened stderr with line buffering\")\n    if _stdout_buffer_result is True:\n        log.debug(\"Reopened stdout with line buffering\")\n    if isinstance(_stdout_buffer_result, Exception) or isinstance(_stderr_buffer_result, Exception):\n        if isinstance(_stdout_buffer_result, Exception):\n            log.warning(\"Failed to ensure that stdout is line buffered\", exc_info=_stdout_buffer_result)\n        if isinstance(_stderr_buffer_result, Exception):\n            log.warning(\"Failed to ensure that stderr is line buffered\", exc_info=_stderr_buffer_result)\n        log.warning(\"Some stack traces may not appear because of this.\")\n\n    del _stderr_buffer_result, _stdout_buffer_result\n\n\n# Singleton scheduler instance\n# NB this cheekily ensures a singleton since we're replacing the reference\n# so that cocotb.scheduler gives you the singleton instance and not the\n# scheduler package\n\nscheduler: Optional[Scheduler] = None\n\"\"\"The global scheduler instance.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nregression_manager: Optional[RegressionManager] = None\n\"\"\"The global regression manager instance.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nargv: Optional[List[str]] = None\n\"\"\"The argument list as seen by the simulator.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nargc: Optional[int] = None\n\"\"\"The length of :data:`cocotb.argv`.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nplusargs: Optional[Dict[str, Union[bool, str]]] = None\n\"\"\"A dictionary of \"plusargs\" handed to the simulation.\n\nSee :make:var:`PLUSARGS` for details.\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nLANGUAGE: Optional[str] = os.getenv(\"TOPLEVEL_LANG\")\n\"\"\"The value of :make:var:`TOPLEVEL_LANG`.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nSIM_NAME: Optional[str] = None\n\"\"\"The running simulator product information.\n\n``None`` if :mod:`cocotb` was not loaded from a simulator.\n\"\"\"\n\nSIM_VERSION: Optional[str] = None\n\"\"\"The version of the running simulator.\n\n``None`` if :mod:`cocotb` was not loaded from a simulator.\"\"\"\n\nRANDOM_SEED: Optional[int] = None\n\"\"\"\nThe value passed to the Python default random number generator.\n\nSee :envvar:`RANDOM_SEED` for details on how the value is computed.\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\n_library_coverage = None\n\"\"\" used for cocotb library coverage \"\"\"\n\ntop: Optional[cocotb.handle.SimHandleBase] = None\nr\"\"\"\nA handle to the :envvar:`TOPLEVEL` entity/module.\n\nThis is equivalent to the :term:`DUT` parameter given to cocotb tests, so it can be used wherever that variable can be used.\nIt is particularly useful for extracting information about the :term:`DUT` in module-level class and function definitions;\nand in parameters to :class:`.TestFactory`\\ s.\n``None`` if :mod:`cocotb` was not loaded from a simulator.\n\"\"\"\n\n\ndef fork(coro: Union[RunningTask, Coroutine]) -> RunningTask:\n    \"\"\" Schedule a coroutine to be run concurrently. See :ref:`coroutines` for details on its use. \"\"\"\n    return scheduler.add(coro)\n\n\n# FIXME is this really required?\n_rlock = threading.RLock()\n\n\ndef mem_debug(port):\n    import cocotb.memdebug\n    cocotb.memdebug.start(port)\n\n\ndef _initialise_testbench(argv_):  # pragma: no cover\n    \"\"\"Initialize testbench.\n\n    This function is called after the simulator has elaborated all\n    entities and is ready to run the test.\n\n    The test must be defined by the environment variables\n    :envvar:`MODULE` and :envvar:`TESTCASE`.\n\n    The environment variable :envvar:`COCOTB_HOOKS`, if present, contains a\n    comma-separated list of modules to be executed before the first test.\n    \"\"\"\n    with _rlock:\n\n        if \"COCOTB_LIBRARY_COVERAGE\" in os.environ:\n            import coverage\n\n            global _library_coverage\n            _library_coverage = coverage.coverage(\n                data_file=\".coverage.cocotb\",\n                branch=True,\n                include=[\"{}/*\".format(os.path.dirname(__file__))])\n            _library_coverage.start()\n\n        return _initialise_testbench_(argv_)\n\n\ndef _initialise_testbench_(argv_):\n    # The body of this function is split in two because no coverage is collected on\n    # the function that starts the coverage. By splitting it in two we get coverage\n    # on most of the function.\n\n    global argc, argv\n    argv = argv_\n    argc = len(argv)\n\n    root_name = os.getenv(\"TOPLEVEL\")\n    if root_name is not None:\n        if root_name == \"\":\n            root_name = None\n        elif '.' in root_name:\n            # Skip any library component of the toplevel\n            root_name = root_name.split(\".\", 1)[1]\n\n    # sys.path normally includes \"\" (the current directory), but does not appear to when python is embedded.\n    # Add it back because users expect to be able to import files in their test directory.\n    # TODO: move this to gpi_embed.cpp\n    sys.path.insert(0, \"\")\n\n    _setup_logging()\n\n    # From https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners\n    # If the user doesn't want to see these, they can always change the global\n    # warning settings in their test module.\n    if not sys.warnoptions:\n        warnings.simplefilter(\"default\")\n\n    from cocotb import simulator\n\n    global SIM_NAME, SIM_VERSION\n    SIM_NAME = simulator.get_simulator_product().strip()\n    SIM_VERSION = simulator.get_simulator_version().strip()\n\n    cocotb.log.info(\"Running on {} version {}\".format(SIM_NAME, SIM_VERSION))\n\n    memcheck_port = os.getenv('MEMCHECK')\n    if memcheck_port is not None:\n        mem_debug(int(memcheck_port))\n\n    log.info(\"Running tests with cocotb v%s from %s\" %\n             (__version__, os.path.dirname(__file__)))\n\n    # Create the base handle type\n\n    process_plusargs()\n\n    global scheduler\n    scheduler = Scheduler()\n\n    # Seed the Python random number generator to make this repeatable\n    global RANDOM_SEED\n    RANDOM_SEED = os.getenv('RANDOM_SEED')\n\n    if RANDOM_SEED is None:\n        if 'ntb_random_seed' in plusargs:\n            RANDOM_SEED = eval(plusargs['ntb_random_seed'])\n        elif 'seed' in plusargs:\n            RANDOM_SEED = eval(plusargs['seed'])\n        else:\n            RANDOM_SEED = int(time.time())\n        log.info(\"Seeding Python random module with %d\" % (RANDOM_SEED))\n    else:\n        RANDOM_SEED = int(RANDOM_SEED)\n        log.info(\"Seeding Python random module with supplied seed %d\" % (RANDOM_SEED))\n    random.seed(RANDOM_SEED)\n\n    # Setup DUT object\n    from cocotb import simulator\n\n    handle = simulator.get_root_handle(root_name)\n    if not handle:\n        raise RuntimeError(\"Can not find root handle ({})\".format(root_name))\n\n    global top\n    top = cocotb.handle.SimHandle(handle)\n\n    try:\n        import pytest\n    except ImportError:\n        log.warning(\"Pytest not found, assertion rewriting will not occur\")\n    else:\n        try:\n            # Install the assertion rewriting hook, which must be done before we\n            # import the test modules.\n            from _pytest.config import Config\n            from _pytest.assertion import install_importhook\n            pytest_conf = Config.fromdictargs([], {})\n            install_importhook(pytest_conf)\n        except Exception:\n            log.exception(\n                \"Configuring the assertion rewrite hook using pytest {} failed. \"\n                \"Please file a bug report!\".format(pytest.__version__))\n\n    # start Regression Manager\n    global regression_manager\n    regression_manager = RegressionManager.from_discovery(top)\n    regression_manager.execute()\n\n    return True\n\n\ndef _sim_event(level, message):\n    \"\"\"Function that can be called externally to signal an event.\"\"\"\n    # SIM_INFO = 0\n    SIM_TEST_FAIL = 1\n    SIM_FAIL = 2\n    from cocotb.result import TestFailure, SimFailure\n\n    if level is SIM_TEST_FAIL:\n        scheduler.log.error(\"Failing test at simulator request\")\n        scheduler._finish_test(TestFailure(\"Failure from external source: {}\".format(message)))\n    elif level is SIM_FAIL:\n        # We simply return here as the simulator will exit\n        # so no cleanup is needed\n        msg = \"Failing test at simulator request before test run completion: {}\".format(message)\n        scheduler.log.error(msg)\n        scheduler._finish_scheduler(SimFailure(msg))\n    else:\n        scheduler.log.error(\"Unsupported sim event\")\n\n    return True\n\n\ndef process_plusargs():\n\n    global plusargs\n\n    plusargs = {}\n\n    for option in cocotb.argv:\n        if option.startswith('+'):\n            if option.find('=') != -1:\n                (name, value) = option[1:].split('=')\n                plusargs[name] = value\n            else:\n                plusargs[option[1:]] = True\n", "path": "cocotb/__init__.py"}], "after_files": [{"content": "# Copyright (c) 2013 Potential Ventures Ltd\n# Copyright (c) 2013 SolarFlare Communications Inc\n# All rights reserved.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, 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\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY\n# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# ON 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\n# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\"\"\"\nCocotb is a coroutine, cosimulation framework for writing testbenches in Python.\n\nSee https://docs.cocotb.org for full documentation\n\"\"\"\nimport os\nimport sys\nimport logging\nimport threading\nimport random\nimport time\nimport warnings\nfrom typing import Dict, List, Optional, Union\nfrom collections.abc import Coroutine\n\nimport cocotb.handle\nimport cocotb.log\nfrom cocotb.scheduler import Scheduler\nfrom cocotb.regression import RegressionManager\nfrom cocotb.decorators import RunningTask\n\n# Things we want in the cocotb namespace\nfrom cocotb.decorators import test, coroutine, hook, function, external  # noqa: F401\n\nfrom ._version import __version__\n\n\ndef _setup_logging():\n    global log\n\n    def _reopen_stream_with_buffering(stream_name):\n        try:\n            if not getattr(sys, stream_name).isatty():\n                setattr(sys, stream_name, os.fdopen(getattr(sys, stream_name).fileno(), 'w', 1))\n                return True\n            return False\n        except Exception as e:\n            return e\n\n    # If stdout/stderr are not TTYs, Python may not have opened them with line\n    # buffering. In that case, try to reopen them with line buffering\n    # explicitly enabled. This ensures that prints such as stack traces always\n    # appear. Continue silently if this fails.\n    _stdout_buffer_result = _reopen_stream_with_buffering('stdout')\n    _stderr_buffer_result = _reopen_stream_with_buffering('stderr')\n\n    # Don't set the logging up until we've attempted to fix the standard IO,\n    # otherwise it will end up connected to the unfixed IO.\n    cocotb.log.default_config()\n    log = logging.getLogger(__name__)\n\n    # we can't log these things until the logging is set up!\n    if _stderr_buffer_result is True:\n        log.debug(\"Reopened stderr with line buffering\")\n    if _stdout_buffer_result is True:\n        log.debug(\"Reopened stdout with line buffering\")\n    if isinstance(_stdout_buffer_result, Exception) or isinstance(_stderr_buffer_result, Exception):\n        if isinstance(_stdout_buffer_result, Exception):\n            log.warning(\"Failed to ensure that stdout is line buffered\", exc_info=_stdout_buffer_result)\n        if isinstance(_stderr_buffer_result, Exception):\n            log.warning(\"Failed to ensure that stderr is line buffered\", exc_info=_stderr_buffer_result)\n        log.warning(\"Some stack traces may not appear because of this.\")\n\n    del _stderr_buffer_result, _stdout_buffer_result\n\n\n# Singleton scheduler instance\n# NB this cheekily ensures a singleton since we're replacing the reference\n# so that cocotb.scheduler gives you the singleton instance and not the\n# scheduler package\n\nscheduler: Optional[Scheduler] = None\n\"\"\"The global scheduler instance.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nregression_manager: Optional[RegressionManager] = None\n\"\"\"The global regression manager instance.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nargv: Optional[List[str]] = None\n\"\"\"The argument list as seen by the simulator.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nargc: Optional[int] = None\n\"\"\"The length of :data:`cocotb.argv`.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nplusargs: Optional[Dict[str, Union[bool, str]]] = None\n\"\"\"A dictionary of \"plusargs\" handed to the simulation.\n\nSee :make:var:`PLUSARGS` for details.\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nLANGUAGE: Optional[str] = os.getenv(\"TOPLEVEL_LANG\")\n\"\"\"The value of :make:var:`TOPLEVEL_LANG`.\n\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\nSIM_NAME: Optional[str] = None\n\"\"\"The running simulator product information.\n\n``None`` if :mod:`cocotb` was not loaded from a simulator.\n\"\"\"\n\nSIM_VERSION: Optional[str] = None\n\"\"\"The version of the running simulator.\n\n``None`` if :mod:`cocotb` was not loaded from a simulator.\"\"\"\n\nRANDOM_SEED: Optional[int] = None\n\"\"\"\nThe value passed to the Python default random number generator.\n\nSee :envvar:`RANDOM_SEED` for details on how the value is computed.\nThis is guaranteed to hold a value at test time.\n\"\"\"\n\n_library_coverage = None\n\"\"\" used for cocotb library coverage \"\"\"\n\ntop: Optional[cocotb.handle.SimHandleBase] = None\nr\"\"\"\nA handle to the :envvar:`TOPLEVEL` entity/module.\n\nThis is equivalent to the :term:`DUT` parameter given to cocotb tests, so it can be used wherever that variable can be used.\nIt is particularly useful for extracting information about the :term:`DUT` in module-level class and function definitions;\nand in parameters to :class:`.TestFactory`\\ s.\n``None`` if :mod:`cocotb` was not loaded from a simulator.\n\"\"\"\n\n\ndef fork(coro: Union[RunningTask, Coroutine]) -> RunningTask:\n    \"\"\" Schedule a coroutine to be run concurrently. See :ref:`coroutines` for details on its use. \"\"\"\n    return scheduler.add(coro)\n\n\n# FIXME is this really required?\n_rlock = threading.RLock()\n\n\ndef mem_debug(port):\n    import cocotb.memdebug\n    cocotb.memdebug.start(port)\n\n\ndef _initialise_testbench(argv_):  # pragma: no cover\n    \"\"\"Initialize testbench.\n\n    This function is called after the simulator has elaborated all\n    entities and is ready to run the test.\n\n    The test must be defined by the environment variables\n    :envvar:`MODULE` and :envvar:`TESTCASE`.\n\n    The environment variable :envvar:`COCOTB_HOOKS`, if present, contains a\n    comma-separated list of modules to be executed before the first test.\n    \"\"\"\n    with _rlock:\n\n        if \"COCOTB_LIBRARY_COVERAGE\" in os.environ:\n            import coverage\n\n            global _library_coverage\n            _library_coverage = coverage.coverage(\n                data_file=\".coverage.cocotb\",\n                branch=True,\n                include=[\"{}/*\".format(os.path.dirname(__file__))])\n            _library_coverage.start()\n\n        return _initialise_testbench_(argv_)\n\n\ndef _initialise_testbench_(argv_):\n    # The body of this function is split in two because no coverage is collected on\n    # the function that starts the coverage. By splitting it in two we get coverage\n    # on most of the function.\n\n    global argc, argv\n    argv = argv_\n    argc = len(argv)\n\n    root_name = os.getenv(\"TOPLEVEL\")\n    if root_name is not None:\n        root_name = root_name.strip()\n        if root_name == \"\":\n            root_name = None\n        elif '.' in root_name:\n            # Skip any library component of the toplevel\n            root_name = root_name.split(\".\", 1)[1]\n\n    # sys.path normally includes \"\" (the current directory), but does not appear to when python is embedded.\n    # Add it back because users expect to be able to import files in their test directory.\n    # TODO: move this to gpi_embed.cpp\n    sys.path.insert(0, \"\")\n\n    _setup_logging()\n\n    # From https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners\n    # If the user doesn't want to see these, they can always change the global\n    # warning settings in their test module.\n    if not sys.warnoptions:\n        warnings.simplefilter(\"default\")\n\n    from cocotb import simulator\n\n    global SIM_NAME, SIM_VERSION\n    SIM_NAME = simulator.get_simulator_product().strip()\n    SIM_VERSION = simulator.get_simulator_version().strip()\n\n    cocotb.log.info(\"Running on {} version {}\".format(SIM_NAME, SIM_VERSION))\n\n    memcheck_port = os.getenv('MEMCHECK')\n    if memcheck_port is not None:\n        mem_debug(int(memcheck_port))\n\n    log.info(\"Running tests with cocotb v%s from %s\" %\n             (__version__, os.path.dirname(__file__)))\n\n    # Create the base handle type\n\n    process_plusargs()\n\n    global scheduler\n    scheduler = Scheduler()\n\n    # Seed the Python random number generator to make this repeatable\n    global RANDOM_SEED\n    RANDOM_SEED = os.getenv('RANDOM_SEED')\n\n    if RANDOM_SEED is None:\n        if 'ntb_random_seed' in plusargs:\n            RANDOM_SEED = eval(plusargs['ntb_random_seed'])\n        elif 'seed' in plusargs:\n            RANDOM_SEED = eval(plusargs['seed'])\n        else:\n            RANDOM_SEED = int(time.time())\n        log.info(\"Seeding Python random module with %d\" % (RANDOM_SEED))\n    else:\n        RANDOM_SEED = int(RANDOM_SEED)\n        log.info(\"Seeding Python random module with supplied seed %d\" % (RANDOM_SEED))\n    random.seed(RANDOM_SEED)\n\n    # Setup DUT object\n    from cocotb import simulator\n\n    handle = simulator.get_root_handle(root_name)\n    if not handle:\n        raise RuntimeError(\"Can not find root handle ({})\".format(root_name))\n\n    global top\n    top = cocotb.handle.SimHandle(handle)\n\n    try:\n        import pytest\n    except ImportError:\n        log.warning(\"Pytest not found, assertion rewriting will not occur\")\n    else:\n        try:\n            # Install the assertion rewriting hook, which must be done before we\n            # import the test modules.\n            from _pytest.config import Config\n            from _pytest.assertion import install_importhook\n            pytest_conf = Config.fromdictargs([], {})\n            install_importhook(pytest_conf)\n        except Exception:\n            log.exception(\n                \"Configuring the assertion rewrite hook using pytest {} failed. \"\n                \"Please file a bug report!\".format(pytest.__version__))\n\n    # start Regression Manager\n    global regression_manager\n    regression_manager = RegressionManager.from_discovery(top)\n    regression_manager.execute()\n\n    return True\n\n\ndef _sim_event(level, message):\n    \"\"\"Function that can be called externally to signal an event.\"\"\"\n    # SIM_INFO = 0\n    SIM_TEST_FAIL = 1\n    SIM_FAIL = 2\n    from cocotb.result import TestFailure, SimFailure\n\n    if level is SIM_TEST_FAIL:\n        scheduler.log.error(\"Failing test at simulator request\")\n        scheduler._finish_test(TestFailure(\"Failure from external source: {}\".format(message)))\n    elif level is SIM_FAIL:\n        # We simply return here as the simulator will exit\n        # so no cleanup is needed\n        msg = \"Failing test at simulator request before test run completion: {}\".format(message)\n        scheduler.log.error(msg)\n        scheduler._finish_scheduler(SimFailure(msg))\n    else:\n        scheduler.log.error(\"Unsupported sim event\")\n\n    return True\n\n\ndef process_plusargs():\n\n    global plusargs\n\n    plusargs = {}\n\n    for option in cocotb.argv:\n        if option.startswith('+'):\n            if option.find('=') != -1:\n                (name, value) = option[1:].split('=')\n                plusargs[name] = value\n            else:\n                plusargs[option[1:]] = True\n", "path": "cocotb/__init__.py"}]}