We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Document cocotb module variables
The `cocotb` module has some important variables which aren't documented:

- [ ] SIM_NAME
- [ ] SIM_VERSION
- [ ] RANDOM_SEED
- [ ] log
- [X] scheduler
- [ ] regression_manager
- [X] plusargs
- [ ] argv/argc
- [ ] LANGUAGE

--- 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 
41 import cocotb._os_compat  # must appear first, before the first import of cocotb.simulator
42 import cocotb.handle
43 import cocotb.log
44 from cocotb.scheduler import Scheduler
45 from cocotb.regression import RegressionManager
46 
47 
48 # Things we want in the cocotb namespace
49 from cocotb.decorators import test, coroutine, hook, function, external  # noqa: F401
50 
51 from ._version import __version__
52 
53 
54 def _setup_logging():
55     global log
56 
57     def _reopen_stream_with_buffering(stream_name):
58         try:
59             if not getattr(sys, stream_name).isatty():
60                 setattr(sys, stream_name, os.fdopen(getattr(sys, stream_name).fileno(), 'w', 1))
61                 return True
62             return False
63         except Exception as e:
64             return e
65 
66     # If stdout/stderr are not TTYs, Python may not have opened them with line
67     # buffering. In that case, try to reopen them with line buffering
68     # explicitly enabled. This ensures that prints such as stack traces always
69     # appear. Continue silently if this fails.
70     _stdout_buffer_result = _reopen_stream_with_buffering('stdout')
71     _stderr_buffer_result = _reopen_stream_with_buffering('stderr')
72 
73     # Don't set the logging up until we've attempted to fix the standard IO,
74     # otherwise it will end up connected to the unfixed IO.
75     cocotb.log.default_config()
76     log = logging.getLogger(__name__)
77 
78     # we can't log these things until the logging is set up!
79     if _stderr_buffer_result is True:
80         log.debug("Reopened stderr with line buffering")
81     if _stdout_buffer_result is True:
82         log.debug("Reopened stdout with line buffering")
83     if isinstance(_stdout_buffer_result, Exception) or isinstance(_stderr_buffer_result, Exception):
84         if isinstance(_stdout_buffer_result, Exception):
85             log.warning("Failed to ensure that stdout is line buffered", exc_info=_stdout_buffer_result)
86         if isinstance(_stderr_buffer_result, Exception):
87             log.warning("Failed to ensure that stderr is line buffered", exc_info=_stderr_buffer_result)
88         log.warning("Some stack traces may not appear because of this.")
89 
90     del _stderr_buffer_result, _stdout_buffer_result
91 
92 
93 # Singleton scheduler instance
94 # NB this cheekily ensures a singleton since we're replacing the reference
95 # so that cocotb.scheduler gives you the singleton instance and not the
96 # scheduler package
97 
98 scheduler = None
99 """The global scheduler instance."""
100 
101 regression_manager = None
102 
103 plusargs = {}
104 """A dictionary of "plusargs" handed to the simulation."""
105 
106 
107 def fork(coro):
108     """ Schedule a coroutine to be run concurrently. See :ref:`coroutines` for details on it's use. """
109     return scheduler.add(coro)
110 
111 
112 # FIXME is this really required?
113 _rlock = threading.RLock()
114 
115 LANGUAGE = os.getenv("TOPLEVEL_LANG")
116 
117 
118 def mem_debug(port):
119     import cocotb.memdebug
120     cocotb.memdebug.start(port)
121 
122 
123 def _initialise_testbench(argv_):
124     """Initialize testbench.
125 
126     This function is called after the simulator has elaborated all
127     entities and is ready to run the test.
128 
129     The test must be defined by the environment variables
130     :envvar:`MODULE` and :envvar:`TESTCASE`.
131 
132     The environment variable :envvar:`COCOTB_HOOKS`, if present, contains a
133     comma-separated list of modules to be executed before the first test.
134     """
135     _rlock.acquire()
136 
137     global argc, argv
138     argv = argv_
139     argc = len(argv)
140 
141     root_name = os.getenv("TOPLEVEL")
142     if root_name is not None:
143         if root_name == "":
144             root_name = None
145         elif '.' in root_name:
146             # Skip any library component of the toplevel
147             root_name = root_name.split(".", 1)[1]
148 
149     # sys.path normally includes "" (the current directory), but does not appear to when python is embedded.
150     # Add it back because users expect to be able to import files in their test directory.
151     # TODO: move this to gpi_embed.cpp
152     sys.path.insert(0, "")
153 
154     _setup_logging()
155 
156     # From https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners
157     # If the user doesn't want to see these, they can always change the global
158     # warning settings in their test module.
159     if not sys.warnoptions:
160         warnings.simplefilter("default")
161 
162     from cocotb import simulator
163 
164     global SIM_NAME, SIM_VERSION
165     SIM_NAME = simulator.get_simulator_product()
166     SIM_VERSION = simulator.get_simulator_version()
167 
168     cocotb.log.info("Running on {} version {}".format(SIM_NAME, SIM_VERSION))
169 
170     memcheck_port = os.getenv('MEMCHECK')
171     if memcheck_port is not None:
172         mem_debug(int(memcheck_port))
173 
174     log.info("Running tests with cocotb v%s from %s" %
175              (__version__, os.path.dirname(__file__)))
176 
177     # Create the base handle type
178 
179     process_plusargs()
180 
181     global scheduler
182     scheduler = Scheduler()
183 
184     # Seed the Python random number generator to make this repeatable
185     global RANDOM_SEED
186     RANDOM_SEED = os.getenv('RANDOM_SEED')
187 
188     if RANDOM_SEED is None:
189         if 'ntb_random_seed' in plusargs:
190             RANDOM_SEED = eval(plusargs['ntb_random_seed'])
191         elif 'seed' in plusargs:
192             RANDOM_SEED = eval(plusargs['seed'])
193         else:
194             RANDOM_SEED = int(time.time())
195         log.info("Seeding Python random module with %d" % (RANDOM_SEED))
196     else:
197         RANDOM_SEED = int(RANDOM_SEED)
198         log.info("Seeding Python random module with supplied seed %d" % (RANDOM_SEED))
199     random.seed(RANDOM_SEED)
200 
201     # Setup DUT object
202     from cocotb import simulator
203 
204     handle = simulator.get_root_handle(root_name)
205     if not handle:
206         raise RuntimeError("Can not find root handle ({})".format(root_name))
207 
208     dut = cocotb.handle.SimHandle(handle)
209 
210     # start Regression Manager
211     global regression_manager
212     regression_manager = RegressionManager.from_discovery(dut)
213     regression_manager.execute()
214 
215     _rlock.release()
216     return True
217 
218 
219 def _sim_event(level, message):
220     """Function that can be called externally to signal an event."""
221     SIM_INFO = 0
222     SIM_TEST_FAIL = 1
223     SIM_FAIL = 2
224     from cocotb.result import TestFailure, SimFailure
225 
226     if level is SIM_TEST_FAIL:
227         scheduler.log.error("Failing test at simulator request")
228         scheduler.finish_test(TestFailure("Failure from external source: %s" %
229                               message))
230     elif level is SIM_FAIL:
231         # We simply return here as the simulator will exit
232         # so no cleanup is needed
233         msg = ("Failing test at simulator request before test run completion: "
234                "%s" % message)
235         scheduler.log.error(msg)
236         scheduler.finish_scheduler(SimFailure(msg))
237     else:
238         scheduler.log.error("Unsupported sim event")
239 
240     return True
241 
242 
243 def process_plusargs():
244 
245     global plusargs
246 
247     plusargs = {}
248 
249     for option in cocotb.argv:
250         if option.startswith('+'):
251             if option.find('=') != -1:
252                 (name, value) = option[1:].split('=')
253                 plusargs[name] = value
254             else:
255                 plusargs[option[1:]] = True
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/__init__.py b/cocotb/__init__.py
--- a/cocotb/__init__.py
+++ b/cocotb/__init__.py
@@ -37,6 +37,7 @@
 import random
 import time
 import warnings
+from typing import Dict, List, Union
 
 import cocotb._os_compat  # must appear first, before the first import of cocotb.simulator
 import cocotb.handle
@@ -95,13 +96,35 @@
 # so that cocotb.scheduler gives you the singleton instance and not the
 # scheduler package
 
-scheduler = None
+scheduler = None  # type: cocotb.scheduler.Scheduler
 """The global scheduler instance."""
 
-regression_manager = None
+regression_manager = None  # type: cocotb.regression.RegressionManager
+"""The global regression manager instance."""
 
-plusargs = {}
-"""A dictionary of "plusargs" handed to the simulation."""
+argv = None  # type: List[str]
+"""The argument list as seen by the simulator"""
+
+argc = None  # type: int
+"""The length of :data:`cocotb.argv`"""
+
+plusargs = None  # type: Dict[str, Union[bool, str]]
+"""A dictionary of "plusargs" handed to the simulation. See :make:var:`PLUSARGS` for details."""
+
+LANGUAGE = os.getenv("TOPLEVEL_LANG")  # type: str
+"""The value of :make:var:`TOPLEVEL_LANG`"""
+
+SIM_NAME = None  # type: str
+"""The running simulator product information. ``None`` if :mod:`cocotb` was not loaded from a simulator"""
+
+SIM_VERSION = None  # type: str
+"""The version of the running simulator. ``None`` if :mod:`cocotb` was not loaded from a simulator"""
+
+RANDOM_SEED = None  # type: int
+"""
+The value passed to the Python default random number generator.
+See :envvar:`RANDOM_SEED` for details on how the value is computed.
+"""
 
 
 def fork(coro):
@@ -112,8 +135,6 @@
 # FIXME is this really required?
 _rlock = threading.RLock()
 
-LANGUAGE = os.getenv("TOPLEVEL_LANG")
-
 
 def mem_debug(port):
     import cocotb.memdebug

{"golden_diff": "diff --git a/cocotb/__init__.py b/cocotb/__init__.py\n--- a/cocotb/__init__.py\n+++ b/cocotb/__init__.py\n@@ -37,6 +37,7 @@\n import random\n import time\n import warnings\n+from typing import Dict, List, Union\n \n import cocotb._os_compat  # must appear first, before the first import of cocotb.simulator\n import cocotb.handle\n@@ -95,13 +96,35 @@\n # so that cocotb.scheduler gives you the singleton instance and not the\n # scheduler package\n \n-scheduler = None\n+scheduler = None  # type: cocotb.scheduler.Scheduler\n \"\"\"The global scheduler instance.\"\"\"\n \n-regression_manager = None\n+regression_manager = None  # type: cocotb.regression.RegressionManager\n+\"\"\"The global regression manager instance.\"\"\"\n \n-plusargs = {}\n-\"\"\"A dictionary of \"plusargs\" handed to the simulation.\"\"\"\n+argv = None  # type: List[str]\n+\"\"\"The argument list as seen by the simulator\"\"\"\n+\n+argc = None  # type: int\n+\"\"\"The length of :data:`cocotb.argv`\"\"\"\n+\n+plusargs = None  # type: Dict[str, Union[bool, str]]\n+\"\"\"A dictionary of \"plusargs\" handed to the simulation. See :make:var:`PLUSARGS` for details.\"\"\"\n+\n+LANGUAGE = os.getenv(\"TOPLEVEL_LANG\")  # type: str\n+\"\"\"The value of :make:var:`TOPLEVEL_LANG`\"\"\"\n+\n+SIM_NAME = None  # type: str\n+\"\"\"The running simulator product information. ``None`` if :mod:`cocotb` was not loaded from a simulator\"\"\"\n+\n+SIM_VERSION = None  # type: str\n+\"\"\"The version of the running simulator. ``None`` if :mod:`cocotb` was not loaded from a simulator\"\"\"\n+\n+RANDOM_SEED = None  # type: int\n+\"\"\"\n+The value passed to the Python default random number generator.\n+See :envvar:`RANDOM_SEED` for details on how the value is computed.\n+\"\"\"\n \n \n def fork(coro):\n@@ -112,8 +135,6 @@\n # FIXME is this really required?\n _rlock = threading.RLock()\n \n-LANGUAGE = os.getenv(\"TOPLEVEL_LANG\")\n-\n \n def mem_debug(port):\n     import cocotb.memdebug\n", "issue": "Document cocotb module variables\nThe `cocotb` module has some important variables which aren't documented:\r\n\r\n- [ ] SIM_NAME\r\n- [ ] SIM_VERSION\r\n- [ ] RANDOM_SEED\r\n- [ ] log\r\n- [X] scheduler\r\n- [ ] regression_manager\r\n- [X] plusargs\r\n- [ ] argv/argc\r\n- [ ] LANGUAGE\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\n\nimport cocotb._os_compat  # must appear first, before the first import of cocotb.simulator\nimport cocotb.handle\nimport cocotb.log\nfrom cocotb.scheduler import Scheduler\nfrom cocotb.regression import RegressionManager\n\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 = None\n\"\"\"The global scheduler instance.\"\"\"\n\nregression_manager = None\n\nplusargs = {}\n\"\"\"A dictionary of \"plusargs\" handed to the simulation.\"\"\"\n\n\ndef fork(coro):\n    \"\"\" Schedule a coroutine to be run concurrently. See :ref:`coroutines` for details on it's use. \"\"\"\n    return scheduler.add(coro)\n\n\n# FIXME is this really required?\n_rlock = threading.RLock()\n\nLANGUAGE = os.getenv(\"TOPLEVEL_LANG\")\n\n\ndef mem_debug(port):\n    import cocotb.memdebug\n    cocotb.memdebug.start(port)\n\n\ndef _initialise_testbench(argv_):\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    _rlock.acquire()\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()\n    SIM_VERSION = simulator.get_simulator_version()\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    dut = cocotb.handle.SimHandle(handle)\n\n    # start Regression Manager\n    global regression_manager\n    regression_manager = RegressionManager.from_discovery(dut)\n    regression_manager.execute()\n\n    _rlock.release()\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: %s\" %\n                              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: \"\n               \"%s\" % 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, Union\n\nimport cocotb._os_compat  # must appear first, before the first import of cocotb.simulator\nimport cocotb.handle\nimport cocotb.log\nfrom cocotb.scheduler import Scheduler\nfrom cocotb.regression import RegressionManager\n\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 = None  # type: cocotb.scheduler.Scheduler\n\"\"\"The global scheduler instance.\"\"\"\n\nregression_manager = None  # type: cocotb.regression.RegressionManager\n\"\"\"The global regression manager instance.\"\"\"\n\nargv = None  # type: List[str]\n\"\"\"The argument list as seen by the simulator\"\"\"\n\nargc = None  # type: int\n\"\"\"The length of :data:`cocotb.argv`\"\"\"\n\nplusargs = None  # type: Dict[str, Union[bool, str]]\n\"\"\"A dictionary of \"plusargs\" handed to the simulation. See :make:var:`PLUSARGS` for details.\"\"\"\n\nLANGUAGE = os.getenv(\"TOPLEVEL_LANG\")  # type: str\n\"\"\"The value of :make:var:`TOPLEVEL_LANG`\"\"\"\n\nSIM_NAME = None  # type: str\n\"\"\"The running simulator product information. ``None`` if :mod:`cocotb` was not loaded from a simulator\"\"\"\n\nSIM_VERSION = None  # type: str\n\"\"\"The version of the running simulator. ``None`` if :mod:`cocotb` was not loaded from a simulator\"\"\"\n\nRANDOM_SEED = None  # type: int\n\"\"\"\nThe value passed to the Python default random number generator.\nSee :envvar:`RANDOM_SEED` for details on how the value is computed.\n\"\"\"\n\n\ndef fork(coro):\n    \"\"\" Schedule a coroutine to be run concurrently. See :ref:`coroutines` for details on it's 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_):\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    _rlock.acquire()\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()\n    SIM_VERSION = simulator.get_simulator_version()\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    dut = cocotb.handle.SimHandle(handle)\n\n    # start Regression Manager\n    global regression_manager\n    regression_manager = RegressionManager.from_discovery(dut)\n    regression_manager.execute()\n\n    _rlock.release()\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: %s\" %\n                              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: \"\n               \"%s\" % 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"}]}