gem5 m5.objects module

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2020-05-07 01:00:00 +00:00
parent f0e6ee9fb2
commit 252dd80500
2 changed files with 153 additions and 1 deletions

View File

@@ -13418,6 +13418,147 @@ and that is where the main event loop, `doSimLoop`, gets called and starts kicki
Tested at gem5 b4879ae5b0b6644e6836b0881e4da05c64a6550d. Tested at gem5 b4879ae5b0b6644e6836b0881e4da05c64a6550d.
===== gem5 `m5.objects` module
All `SimObjects` seem to be automatically added to the `m5.objects` namespace, and this is done in a very convoluted way, let's try to understand a bit:
....
src/python/m5/objects/__init__.py
....
contains:
....
modules = __loader__.modules
for module in modules.keys():
if module.startswith('m5.objects.'):
exec("from %s import *" % module)
....
And from <<debug-gem5-python-scripts,IPDB>> we see that this appears to loop over every object string of type `m5.objects.modulename`.
This `__init__` gets called from `src/python/importer.py` at the `exec`:
....
class CodeImporter(object):
def load_module(self, fullname):
override = os.environ.get('M5_OVERRIDE_PY_SOURCE', 'false').lower()
if override in ('true', 'yes') and os.path.exists(abspath):
src = open(abspath, 'r').read()
code = compile(src, abspath, 'exec')
if os.path.basename(srcfile) == '__init__.py':
mod.__path__ = fullname.split('.')
mod.__package__ = fullname
else:
mod.__package__ = fullname.rpartition('.')[0]
mod.__file__ = srcfile
exec(code, mod.__dict__)
import sys
importer = CodeImporter()
add_module = importer.add_module
sys.meta_path.append(importer)
....
Here as a bonus here we also see how <<m5-override-py-source,`M5_OVERRIDE_PY_SOURCE`>> works.
In `src/SConscript` we see that `SimObject` is just a `PySource` with module equals to `m5.objects`:
....
class SimObject(PySource):
def __init__(self, source, tags=None, add_tags=None):
'''Specify the source file and any tags (automatically in
the m5.objects package)'''
super(SimObject, self).__init__('m5.objects', source, tags, add_tags)
....
The `add_module` method seems to be doing the magic and is called from `src/sim/init.cc`:
....
bool
EmbeddedPython::addModule() const
{
PyObject *code = getCode();
PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"),
....
which is called from:
....
int
EmbeddedPython::initAll()
{
// Load the importer module
PyObject *code = importer->getCode();
importerModule = PyImport_ExecCodeModule(PyCC("importer"), code);
if (!importerModule) {
PyErr_Print();
return 1;
}
// Load the rest of the embedded python files into the embedded
// python importer
list<EmbeddedPython *>::iterator i = getList().begin();
list<EmbeddedPython *>::iterator end = getList().end();
for (; i != end; ++i)
if (!(*i)->addModule())
....
and `getList` comes from:
....
EmbeddedPython::EmbeddedPython(const char *filename, const char *abspath,
const char *modpath, const unsigned char *code, int zlen, int len)
: filename(filename), abspath(abspath), modpath(modpath), code(code),
zlen(zlen), len(len)
{
// if we've added the importer keep track of it because we need it
// to bootstrap.
if (string(modpath) == string("importer"))
importer = this;
else
getList().push_back(this);
}
list<EmbeddedPython *> &
EmbeddedPython::getList()
{
static list<EmbeddedPython *> the_list;
return the_list;
}
....
and the constructor in turn gets called from per `SimObject` autogenerated files such as e.g. `dev/storage/Ide.py.cc` for `src/dev/storage/Ide.py`:
....
EmbeddedPython embedded_m5_objects_Ide(
"m5/objects/Ide.py",
"/home/ciro/bak/git/linux-kernel-module-cheat/data/gem5/master4/src/dev/storage/Ide.py",
"m5.objects.Ide",
data_m5_objects_Ide,
947,
2099);
} // anonymous namespace
....
which get autogenerated at `src/SConscript`:
....
def embedPyFile(target, source, env):
for source in PySource.all:
base_py_env.Command(source.cpp, [ py_marshal, source.tnode ],
MakeAction(embedPyFile, Transform("EMBED PY")))
....
where the `PySource.all` thing as you might expect is a static list of all `PySource` source files as they get updated in the constructor.
Tested in gem5 d9cb548d83fa81858599807f54b52e5be35a6b03.
==== gem5 event queue ==== gem5 event queue
gem5 is an event based simulator, and as such the event queue is of of the crucial elements in the system. gem5 is an event based simulator, and as such the event queue is of of the crucial elements in the system.
@@ -16248,6 +16389,17 @@ Bibliography: https://www.mail-archive.com/gem5-users@gem5.org/msg16989.html
==== gem5 build system ==== gem5 build system
[[m5-override-py-source]]
===== M5_OVERRIDE_PY_SOURCE
https://stackoverflow.com/questions/52312070/how-to-modify-a-file-under-src-python-and-run-it-without-rebuilding-in-gem5
Running gem5 with the `M5_OVERRIDE_PY_SOURCE=true` environment variable allows you to modify a file under src/python and run it without rebuilding in gem5?
We set this environment variable by default in our link:run[] script.
How `M5_OVERRID_PY_SOURCE` works is shown at: <<gem5-m5-objects-module>>.
===== gem5 build broken on recent compiler version ===== gem5 build broken on recent compiler version
gem5 moves a bit slowly, and if your host compiler is very new, the gem5 build might be broken for it, e.g. this was the case for Ubuntu 19.10 with GCC 9 and gem5 62d75e7105fe172eb906d4f80f360ff8591d4178 from Dec 2019. gem5 moves a bit slowly, and if your host compiler is very new, the gem5 build might be broken for it, e.g. this was the case for Ubuntu 19.10 with GCC 9 and gem5 62d75e7105fe172eb906d4f80f360ff8591d4178 from Dec 2019.

2
run
View File

@@ -518,7 +518,7 @@ Extra options to append at the end of the emulator command line.
gem5_exe_args = self.sh.shlex_split(self.env['gem5_exe_args']) gem5_exe_args = self.sh.shlex_split(self.env['gem5_exe_args'])
if do_trace: if do_trace:
gem5_exe_args.extend(['--debug-flags', trace_type, LF]) gem5_exe_args.extend(['--debug-flags', trace_type, LF])
# https://stackoverflow.com/questions/52312070/how-to-modify-a-file-under-src-python-and-run-it-without-rebuilding-in-gem5/52312071#52312071 # https://cirosantilli.com/linux-kernel-module-cheat#m5-override-py-source
extra_env['M5_OVERRIDE_PY_SOURCE'] = 'true' extra_env['M5_OVERRIDE_PY_SOURCE'] = 'true'
if self.env['trace_stdout']: if self.env['trace_stdout']:
debug_file = 'cout' debug_file = 'cout'