We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make random seed accessible by cocotb tests
I use the numpy package in my cocotb tests. I want to seed the numpy random generator to make numpy's randomization predictable.
Cocotb does this for python's `random ` package in the [`__init__.py`](https://github.com/potentialventures/cocotb/blob/master/cocotb/__init__.py#L138) using `seed` variable. By making `seed` `global` type it can be accessed in `cocotb.test` as `cocotb.seed`. 
This allows the following: `numpy.random.seed(cocotb.seed)` which solves the problem.

I know that this is a one-liner but I don't know if this is the correct approach. Please review my proposal, thanks.
Make random seed accessible by cocotb tests
I use the numpy package in my cocotb tests. I want to seed the numpy random generator to make numpy's randomization predictable.
Cocotb does this for python's `random ` package in the [`__init__.py`](https://github.com/potentialventures/cocotb/blob/master/cocotb/__init__.py#L138) using `seed` variable. By making `seed` `global` type it can be accessed in `cocotb.test` as `cocotb.seed`. 
This allows the following: `numpy.random.seed(cocotb.seed)` which solves the problem.

I know that this is a one-liner but I don't know if this is the correct approach. Please review my proposal, thanks.

--- 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 http://cocotb.readthedocs.org for full documentation
32 """
33 import os
34 import sys
35 import logging
36 import threading
37 import random
38 import time
39 
40 import cocotb.handle
41 from cocotb.scheduler import Scheduler
42 from cocotb.log import SimLogFormatter, SimBaseLog, SimLog
43 from cocotb.regression import RegressionManager
44 
45 
46 # Things we want in the cocotb namespace
47 from cocotb.decorators import test, coroutine, hook, function, external
48 
49 # Singleton scheduler instance
50 # NB this cheekily ensures a singleton since we're replacing the reference
51 # so that cocotb.scheduler gives you the singleton instance and not the
52 # scheduler package
53 
54 # GPI logging instance
55 if "COCOTB_SIM" in os.environ:
56     import simulator
57     logging.basicConfig()
58     logging.setLoggerClass(SimBaseLog)
59     log = SimLog('cocotb')
60     level = os.getenv("COCOTB_LOG_LEVEL", "INFO")
61     try:
62         _default_log = getattr(logging, level)
63     except AttributeError as e:
64         log.error("Unable to set loging level to %s" % level)
65         _default_log = logging.INFO
66     log.setLevel(_default_log)
67     loggpi = SimLog('cocotb.gpi')
68     # Notify GPI of log level
69     simulator.log_level(_default_log)
70 
71     # If stdout/stderr are not TTYs, Python may not have opened them with line
72     # buffering. In that case, try to reopen them with line buffering
73     # explicitly enabled. This ensures that prints such as stack traces always
74     # appear. Continue silently if this fails.
75     try:
76         if not sys.stdout.isatty():
77             sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
78             log.debug("Reopened stdout with line buffering")
79         if not sys.stderr.isatty():
80             sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)
81             log.debug("Reopened stderr with line buffering")
82     except Exception as e:
83         log.warning("Failed to ensure that stdout/stderr are line buffered: %s", e)
84         log.warning("Some stack traces may not appear because of this.")
85 
86 
87 scheduler = Scheduler()
88 regression_manager = None
89 
90 plusargs = {}
91 
92 # To save typing provide an alias to scheduler.add
93 fork = scheduler.add
94 
95 # FIXME is this really required?
96 _rlock = threading.RLock()
97 
98 
99 def mem_debug(port):
100     import cocotb.memdebug
101     cocotb.memdebug.start(port)
102 
103 
104 def _initialise_testbench(root_name):
105     """
106     This function is called after the simulator has elaborated all
107     entities and is ready to run the test.
108 
109     The test must be defined by the environment variables
110         MODULE
111         TESTCASE
112 
113     The environment variable COCOTB_HOOKS contains a comma-separated list of
114         modules that should be executed before the first test.
115     """
116     _rlock.acquire()
117 
118     memcheck_port = os.getenv('MEMCHECK')
119     if memcheck_port is not None:
120         mem_debug(int(memcheck_port))
121 
122     exec_path = os.getenv('COCOTB_PY_DIR')
123     if exec_path is None:
124         exec_path = 'Unknown'
125 
126     version = os.getenv('VERSION')
127     if version is None:
128         log.info("Unable to determine Cocotb version from %s" % exec_path)
129     else:
130         log.info("Running tests with Cocotb v%s from %s" %
131                  (version, exec_path))
132 
133     # Create the base handle type
134 
135     process_plusargs()
136 
137     # Seed the Python random number generator to make this repeatable
138     seed = os.getenv('RANDOM_SEED')
139 
140     if seed is None:
141         if 'ntb_random_seed' in plusargs:
142             seed = eval(plusargs['ntb_random_seed'])
143         elif 'seed' in plusargs:
144             seed = eval(plusargs['seed'])
145         else:
146             seed = int(time.time())
147         log.info("Seeding Python random module with %d" % (seed))
148     else:
149         seed = int(seed)
150         log.info("Seeding Python random module with supplied seed %d" % (seed))
151     random.seed(seed)
152 
153     module_str = os.getenv('MODULE')
154     test_str = os.getenv('TESTCASE')
155     hooks_str = os.getenv('COCOTB_HOOKS', '')
156 
157     if not module_str:
158         raise ImportError("Environment variables defining the module(s) to " +
159                           "execute not defined.  MODULE=\"%s\"" % (module_str))
160 
161     modules = module_str.split(',')
162     hooks = hooks_str.split(',') if hooks_str else []
163 
164     global regression_manager
165 
166     regression_manager = RegressionManager(root_name, modules, tests=test_str, seed=seed, hooks=hooks)
167     regression_manager.initialise()
168     regression_manager.execute()
169 
170     _rlock.release()
171     return True
172 
173 
174 def _sim_event(level, message):
175     """Function that can be called externally to signal an event"""
176     SIM_INFO = 0
177     SIM_TEST_FAIL = 1
178     SIM_FAIL = 2
179     from cocotb.result import TestFailure, SimFailure
180 
181     if level is SIM_TEST_FAIL:
182         scheduler.log.error("Failing test at simulator request")
183         scheduler.finish_test(TestFailure("Failure from external source: %s" %
184                               message))
185     elif level is SIM_FAIL:
186         # We simply return here as the simulator will exit
187         # so no cleanup is needed
188         msg = ("Failing test at simulator request before test run completion: "
189                "%s" % message)
190         scheduler.log.error(msg)
191         scheduler.finish_scheduler(SimFailure(msg))
192     else:
193         scheduler.log.error("Unsupported sim event")
194 
195     return True
196 
197 
198 def process_plusargs():
199 
200     global plusargs
201 
202     plusargs = {}
203 
204     for option in cocotb.argv:
205         if option.startswith('+'):
206             if option.find('=') != -1:
207                 (name, value) = option[1:].split('=')
208                 plusargs[name] = value
209             else:
210                 plusargs[option[1:]] = True
211
```
--- 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
@@ -135,20 +135,21 @@
     process_plusargs()
 
     # Seed the Python random number generator to make this repeatable
-    seed = os.getenv('RANDOM_SEED')
+    global RANDOM_SEED
+    RANDOM_SEED = os.getenv('RANDOM_SEED')
 
-    if seed is None:
+    if RANDOM_SEED is None:
         if 'ntb_random_seed' in plusargs:
-            seed = eval(plusargs['ntb_random_seed'])
+            RANDOM_SEED = eval(plusargs['ntb_random_seed'])
         elif 'seed' in plusargs:
-            seed = eval(plusargs['seed'])
+            RANDOM_SEED = eval(plusargs['seed'])
         else:
-            seed = int(time.time())
-        log.info("Seeding Python random module with %d" % (seed))
+            RANDOM_SEED = int(time.time())
+        log.info("Seeding Python random module with %d" % (RANDOM_SEED))
     else:
-        seed = int(seed)
-        log.info("Seeding Python random module with supplied seed %d" % (seed))
-    random.seed(seed)
+        RANDOM_SEED = int(RANDOM_SEED)
+        log.info("Seeding Python random module with supplied seed %d" % (RANDOM_SEED))
+    random.seed(RANDOM_SEED)
 
     module_str = os.getenv('MODULE')
     test_str = os.getenv('TESTCASE')
@@ -163,7 +164,7 @@
 
     global regression_manager
 
-    regression_manager = RegressionManager(root_name, modules, tests=test_str, seed=seed, hooks=hooks)
+    regression_manager = RegressionManager(root_name, modules, tests=test_str, seed=RANDOM_SEED, hooks=hooks)
     regression_manager.initialise()
     regression_manager.execute()

{"golden_diff": "diff --git a/cocotb/__init__.py b/cocotb/__init__.py\n--- a/cocotb/__init__.py\n+++ b/cocotb/__init__.py\n@@ -135,20 +135,21 @@\n     process_plusargs()\n \n     # Seed the Python random number generator to make this repeatable\n-    seed = os.getenv('RANDOM_SEED')\n+    global RANDOM_SEED\n+    RANDOM_SEED = os.getenv('RANDOM_SEED')\n \n-    if seed is None:\n+    if RANDOM_SEED is None:\n         if 'ntb_random_seed' in plusargs:\n-            seed = eval(plusargs['ntb_random_seed'])\n+            RANDOM_SEED = eval(plusargs['ntb_random_seed'])\n         elif 'seed' in plusargs:\n-            seed = eval(plusargs['seed'])\n+            RANDOM_SEED = eval(plusargs['seed'])\n         else:\n-            seed = int(time.time())\n-        log.info(\"Seeding Python random module with %d\" % (seed))\n+            RANDOM_SEED = int(time.time())\n+        log.info(\"Seeding Python random module with %d\" % (RANDOM_SEED))\n     else:\n-        seed = int(seed)\n-        log.info(\"Seeding Python random module with supplied seed %d\" % (seed))\n-    random.seed(seed)\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     module_str = os.getenv('MODULE')\n     test_str = os.getenv('TESTCASE')\n@@ -163,7 +164,7 @@\n \n     global regression_manager\n \n-    regression_manager = RegressionManager(root_name, modules, tests=test_str, seed=seed, hooks=hooks)\n+    regression_manager = RegressionManager(root_name, modules, tests=test_str, seed=RANDOM_SEED, hooks=hooks)\n     regression_manager.initialise()\n     regression_manager.execute()\n", "issue": "Make random seed accessible by cocotb tests\nI use the numpy package in my cocotb tests. I want to seed the numpy random generator to make numpy's randomization predictable.\r\nCocotb does this for python's `random ` package in the [`__init__.py`](https://github.com/potentialventures/cocotb/blob/master/cocotb/__init__.py#L138) using `seed` variable. By making `seed` `global` type it can be accessed in `cocotb.test` as `cocotb.seed`. \r\nThis allows the following: `numpy.random.seed(cocotb.seed)` which solves the problem.\r\n\r\nI know that this is a one-liner but I don't know if this is the correct approach. Please review my proposal, thanks.\nMake random seed accessible by cocotb tests\nI use the numpy package in my cocotb tests. I want to seed the numpy random generator to make numpy's randomization predictable.\r\nCocotb does this for python's `random ` package in the [`__init__.py`](https://github.com/potentialventures/cocotb/blob/master/cocotb/__init__.py#L138) using `seed` variable. By making `seed` `global` type it can be accessed in `cocotb.test` as `cocotb.seed`. \r\nThis allows the following: `numpy.random.seed(cocotb.seed)` which solves the problem.\r\n\r\nI know that this is a one-liner but I don't know if this is the correct approach. Please review my proposal, thanks.\n", "before_files": [{"content": "''' 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\"\"\"\nCocotb is a coroutine, cosimulation framework for writing testbenches in Python.\n\nSee http://cocotb.readthedocs.org for full documentation\n\"\"\"\nimport os\nimport sys\nimport logging\nimport threading\nimport random\nimport time\n\nimport cocotb.handle\nfrom cocotb.scheduler import Scheduler\nfrom cocotb.log import SimLogFormatter, SimBaseLog, SimLog\nfrom cocotb.regression import RegressionManager\n\n\n# Things we want in the cocotb namespace\nfrom cocotb.decorators import test, coroutine, hook, function, external\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\n# GPI logging instance\nif \"COCOTB_SIM\" in os.environ:\n    import simulator\n    logging.basicConfig()\n    logging.setLoggerClass(SimBaseLog)\n    log = SimLog('cocotb')\n    level = os.getenv(\"COCOTB_LOG_LEVEL\", \"INFO\")\n    try:\n        _default_log = getattr(logging, level)\n    except AttributeError as e:\n        log.error(\"Unable to set loging level to %s\" % level)\n        _default_log = logging.INFO\n    log.setLevel(_default_log)\n    loggpi = SimLog('cocotb.gpi')\n    # Notify GPI of log level\n    simulator.log_level(_default_log)\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    try:\n        if not sys.stdout.isatty():\n            sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)\n            log.debug(\"Reopened stdout with line buffering\")\n        if not sys.stderr.isatty():\n            sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)\n            log.debug(\"Reopened stderr with line buffering\")\n    except Exception as e:\n        log.warning(\"Failed to ensure that stdout/stderr are line buffered: %s\", e)\n        log.warning(\"Some stack traces may not appear because of this.\")\n\n\nscheduler = Scheduler()\nregression_manager = None\n\nplusargs = {}\n\n# To save typing provide an alias to scheduler.add\nfork = scheduler.add\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(root_name):\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        MODULE\n        TESTCASE\n\n    The environment variable COCOTB_HOOKS contains a comma-separated list of\n        modules that should be executed before the first test.\n    \"\"\"\n    _rlock.acquire()\n\n    memcheck_port = os.getenv('MEMCHECK')\n    if memcheck_port is not None:\n        mem_debug(int(memcheck_port))\n\n    exec_path = os.getenv('COCOTB_PY_DIR')\n    if exec_path is None:\n        exec_path = 'Unknown'\n\n    version = os.getenv('VERSION')\n    if version is None:\n        log.info(\"Unable to determine Cocotb version from %s\" % exec_path)\n    else:\n        log.info(\"Running tests with Cocotb v%s from %s\" %\n                 (version, exec_path))\n\n    # Create the base handle type\n\n    process_plusargs()\n\n    # Seed the Python random number generator to make this repeatable\n    seed = os.getenv('RANDOM_SEED')\n\n    if seed is None:\n        if 'ntb_random_seed' in plusargs:\n            seed = eval(plusargs['ntb_random_seed'])\n        elif 'seed' in plusargs:\n            seed = eval(plusargs['seed'])\n        else:\n            seed = int(time.time())\n        log.info(\"Seeding Python random module with %d\" % (seed))\n    else:\n        seed = int(seed)\n        log.info(\"Seeding Python random module with supplied seed %d\" % (seed))\n    random.seed(seed)\n\n    module_str = os.getenv('MODULE')\n    test_str = os.getenv('TESTCASE')\n    hooks_str = os.getenv('COCOTB_HOOKS', '')\n\n    if not module_str:\n        raise ImportError(\"Environment variables defining the module(s) to \" +\n                          \"execute not defined.  MODULE=\\\"%s\\\"\" % (module_str))\n\n    modules = module_str.split(',')\n    hooks = hooks_str.split(',') if hooks_str else []\n\n    global regression_manager\n\n    regression_manager = RegressionManager(root_name, modules, tests=test_str, seed=seed, hooks=hooks)\n    regression_manager.initialise()\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\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\"\"\"\nCocotb is a coroutine, cosimulation framework for writing testbenches in Python.\n\nSee http://cocotb.readthedocs.org for full documentation\n\"\"\"\nimport os\nimport sys\nimport logging\nimport threading\nimport random\nimport time\n\nimport cocotb.handle\nfrom cocotb.scheduler import Scheduler\nfrom cocotb.log import SimLogFormatter, SimBaseLog, SimLog\nfrom cocotb.regression import RegressionManager\n\n\n# Things we want in the cocotb namespace\nfrom cocotb.decorators import test, coroutine, hook, function, external\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\n# GPI logging instance\nif \"COCOTB_SIM\" in os.environ:\n    import simulator\n    logging.basicConfig()\n    logging.setLoggerClass(SimBaseLog)\n    log = SimLog('cocotb')\n    level = os.getenv(\"COCOTB_LOG_LEVEL\", \"INFO\")\n    try:\n        _default_log = getattr(logging, level)\n    except AttributeError as e:\n        log.error(\"Unable to set loging level to %s\" % level)\n        _default_log = logging.INFO\n    log.setLevel(_default_log)\n    loggpi = SimLog('cocotb.gpi')\n    # Notify GPI of log level\n    simulator.log_level(_default_log)\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    try:\n        if not sys.stdout.isatty():\n            sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)\n            log.debug(\"Reopened stdout with line buffering\")\n        if not sys.stderr.isatty():\n            sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)\n            log.debug(\"Reopened stderr with line buffering\")\n    except Exception as e:\n        log.warning(\"Failed to ensure that stdout/stderr are line buffered: %s\", e)\n        log.warning(\"Some stack traces may not appear because of this.\")\n\n\nscheduler = Scheduler()\nregression_manager = None\n\nplusargs = {}\n\n# To save typing provide an alias to scheduler.add\nfork = scheduler.add\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(root_name):\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        MODULE\n        TESTCASE\n\n    The environment variable COCOTB_HOOKS contains a comma-separated list of\n        modules that should be executed before the first test.\n    \"\"\"\n    _rlock.acquire()\n\n    memcheck_port = os.getenv('MEMCHECK')\n    if memcheck_port is not None:\n        mem_debug(int(memcheck_port))\n\n    exec_path = os.getenv('COCOTB_PY_DIR')\n    if exec_path is None:\n        exec_path = 'Unknown'\n\n    version = os.getenv('VERSION')\n    if version is None:\n        log.info(\"Unable to determine Cocotb version from %s\" % exec_path)\n    else:\n        log.info(\"Running tests with Cocotb v%s from %s\" %\n                 (version, exec_path))\n\n    # Create the base handle type\n\n    process_plusargs()\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    module_str = os.getenv('MODULE')\n    test_str = os.getenv('TESTCASE')\n    hooks_str = os.getenv('COCOTB_HOOKS', '')\n\n    if not module_str:\n        raise ImportError(\"Environment variables defining the module(s) to \" +\n                          \"execute not defined.  MODULE=\\\"%s\\\"\" % (module_str))\n\n    modules = module_str.split(',')\n    hooks = hooks_str.split(',') if hooks_str else []\n\n    global regression_manager\n\n    regression_manager = RegressionManager(root_name, modules, tests=test_str, seed=RANDOM_SEED, hooks=hooks)\n    regression_manager.initialise()\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"}]}