misc: Run pre-commit run on all files in repo

The following command was run:

```
pre-commit run --all-files
```

This ensures all the files in the repository are formatted to pass our
checks.

Change-Id: Ia2fe3529a50ad925d1076a612d60a4280adc40de
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/62572
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
This commit is contained in:
Bobby R. Bruce
2022-08-22 12:34:19 -07:00
committed by Bobby Bruce
parent 64add0e04d
commit 2bc5a8b71a
181 changed files with 1445 additions and 1229 deletions

View File

@@ -331,4 +331,3 @@ Marjan Fariborz <mfariborz@ucdavis.edu> marjanfariborz <mfariborz@ucdavis.edu>
Mike Upton <michaelupton@gmail.com> Mike Upton <michaelupton@gmail.com>
seanzw <seanyukigeek@gmail.com> seanzw <seanyukigeek@gmail.com>
Trivikram Reddy <tvreddy@ucdavis.edu> tv-reddy <tvreddy@ucdavis.edu> Trivikram Reddy <tvreddy@ucdavis.edu> tv-reddy <tvreddy@ucdavis.edu>

View File

@@ -246,10 +246,9 @@ maintainer (see MAINTAINERS).*
## Running Tests in Parallel ## Running Tests in Parallel
Whimsy has support for parallel testing baked in. This system supports Whimsy has support for parallel testing baked in. This system supports
running multiple suites at the same time on the same computer. To run running multiple suites at the same time on the same computer. To run
suites in parallel, supply the `-t <number-tests>` flag to the run command. suites in parallel, supply the `-t <number-tests>` flag to the run command.
For example, to run up to three test suites at the same time:: For example, to run up to three test suites at the same time::
./main.py run --skip-build -t 3 ./main.py run --skip-build -t 3

View File

@@ -26,16 +26,17 @@
import array import array
import functools import functools
def bytesToCppArray(code, symbol, data): def bytesToCppArray(code, symbol, data):
''' """
Output an array of bytes to a code formatter as a c++ array declaration. Output an array of bytes to a code formatter as a c++ array declaration.
''' """
code('const std::uint8_t ${symbol}[] = {') code("const std::uint8_t ${symbol}[] = {")
code.indent() code.indent()
step = 16 step = 16
for i in range(0, len(data), step): for i in range(0, len(data), step):
x = array.array('B', data[i:i+step]) x = array.array("B", data[i : i + step])
strs = map(lambda i: f'{i},', x) strs = map(lambda i: f"{i},", x)
code(functools.reduce(lambda x, y: x + y, strs)) code(functools.reduce(lambda x, y: x + y, strs))
code.dedent() code.dedent()
code('};') code("};")

View File

@@ -45,6 +45,7 @@ import inspect
import os import os
import re import re
class lookup(object): class lookup(object):
def __init__(self, formatter, frame, *args, **kwargs): def __init__(self, formatter, frame, *args, **kwargs):
self.frame = frame self.frame = frame
@@ -64,10 +65,10 @@ class lookup(object):
if item in self.kwargs: if item in self.kwargs:
return self.kwargs[item] return self.kwargs[item]
if item == '__file__': if item == "__file__":
return self.frame.f_code.co_filename return self.frame.f_code.co_filename
if item == '__line__': if item == "__line__":
return self.frame.f_lineno return self.frame.f_lineno
if self.formatter.locals and item in self.frame.f_locals: if self.formatter.locals and item in self.frame.f_locals:
@@ -89,6 +90,7 @@ class lookup(object):
pass pass
raise IndexError("Could not find '%s'" % item) raise IndexError("Could not find '%s'" % item)
class code_formatter_meta(type): class code_formatter_meta(type):
pattern = r""" pattern = r"""
(?: (?:
@@ -102,44 +104,48 @@ class code_formatter_meta(type):
%(delim)s(?P<invalid>) # ill-formed delimiter exprs %(delim)s(?P<invalid>) # ill-formed delimiter exprs
) )
""" """
def __init__(cls, name, bases, dct): def __init__(cls, name, bases, dct):
super(code_formatter_meta, cls).__init__(name, bases, dct) super(code_formatter_meta, cls).__init__(name, bases, dct)
if 'pattern' in dct: if "pattern" in dct:
pat = cls.pattern pat = cls.pattern
else: else:
# tuple expansion to ensure strings are proper length # tuple expansion to ensure strings are proper length
lb,rb = cls.braced lb, rb = cls.braced
lb1,lb2,rb2,rb1 = cls.double_braced lb1, lb2, rb2, rb1 = cls.double_braced
pat = code_formatter_meta.pattern % { pat = code_formatter_meta.pattern % {
'delim' : re.escape(cls.delim), "delim": re.escape(cls.delim),
'ident' : cls.ident, "ident": cls.ident,
'pos' : cls.pos, "pos": cls.pos,
'lb' : re.escape(lb), "lb": re.escape(lb),
'rb' : re.escape(rb), "rb": re.escape(rb),
'ldb' : re.escape(lb1+lb2), "ldb": re.escape(lb1 + lb2),
'rdb' : re.escape(rb2+rb1), "rdb": re.escape(rb2 + rb1),
} }
cls.pattern = re.compile(pat, re.VERBOSE | re.DOTALL | re.MULTILINE) cls.pattern = re.compile(pat, re.VERBOSE | re.DOTALL | re.MULTILINE)
class code_formatter(object, metaclass=code_formatter_meta): class code_formatter(object, metaclass=code_formatter_meta):
delim = r'$' delim = r"$"
ident = r'[_A-z]\w*' ident = r"[_A-z]\w*"
pos = r'[0-9]+' pos = r"[0-9]+"
braced = r'{}' braced = r"{}"
double_braced = r'{{}}' double_braced = r"{{}}"
globals = True globals = True
locals = True locals = True
fix_newlines = True fix_newlines = True
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self._data = [] self._data = []
self._dict = {} self._dict = {}
self._indent_level = 0 self._indent_level = 0
self._indent_spaces = 4 self._indent_spaces = 4
self.globals = kwargs.pop('globals', type(self).globals) self.globals = kwargs.pop("globals", type(self).globals)
self.locals = kwargs.pop('locals', type(self).locals) self.locals = kwargs.pop("locals", type(self).locals)
self._fix_newlines = \ self._fix_newlines = kwargs.pop(
kwargs.pop('fix_newlines', type(self).fix_newlines) "fix_newlines", type(self).fix_newlines
)
if args: if args:
self.__call__(args) self.__call__(args)
@@ -171,38 +177,44 @@ class code_formatter(object, metaclass=code_formatter_meta):
# Add a comment to inform which file generated the generated file # Add a comment to inform which file generated the generated file
# to make it easier to backtrack and modify generated code # to make it easier to backtrack and modify generated code
frame = inspect.currentframe().f_back frame = inspect.currentframe().f_back
if re.match(r'^\.(cc|hh|c|h)$', extension) is not None: if re.match(r"^\.(cc|hh|c|h)$", extension) is not None:
f.write(f'''/** f.write(
f"""/**
* DO NOT EDIT THIS FILE! * DO NOT EDIT THIS FILE!
* File automatically generated by * File automatically generated by
* {frame.f_code.co_filename}:{frame.f_lineno} * {frame.f_code.co_filename}:{frame.f_lineno}
*/ */
''') """
elif re.match(r'^\.py$', extension) is not None: )
f.write(f'''# elif re.match(r"^\.py$", extension) is not None:
f.write(
f"""#
# DO NOT EDIT THIS FILE! # DO NOT EDIT THIS FILE!
# File automatically generated by # File automatically generated by
# {frame.f_code.co_filename}:{frame.f_lineno} # {frame.f_code.co_filename}:{frame.f_lineno}
# #
''') """
elif re.match(r'^\.html$', extension) is not None: )
f.write(f'''<!-- elif re.match(r"^\.html$", extension) is not None:
f.write(
f"""<!--
DO NOT EDIT THIS FILE! DO NOT EDIT THIS FILE!
File automatically generated by File automatically generated by
{frame.f_code.co_filename}:{frame.f_lineno} {frame.f_code.co_filename}:{frame.f_lineno}
--> -->
''') """
)
for data in self._data: for data in self._data:
f.write(data) f.write(data)
f.close() f.close()
def __str__(self): def __str__(self):
data = ''.join(self._data) data = "".join(self._data)
self._data = [ data ] self._data = [data]
return data return data
def __getitem__(self, item): def __getitem__(self, item):
@@ -231,21 +243,21 @@ class code_formatter(object, metaclass=code_formatter_meta):
self._data.append(data) self._data.append(data)
return return
initial_newline = not self._data or self._data[-1] == '\n' initial_newline = not self._data or self._data[-1] == "\n"
for line in data.splitlines(): for line in data.splitlines():
if line: if line:
if self._indent_level: if self._indent_level:
self._data.append(' ' * self._indent_level) self._data.append(" " * self._indent_level)
self._data.append(line) self._data.append(line)
if line or not initial_newline: if line or not initial_newline:
self._data.append('\n') self._data.append("\n")
initial_newline = False initial_newline = False
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
if not args: if not args:
self._data.append('\n') self._data.append("\n")
return return
format = args[0] format = args[0]
@@ -254,51 +266,56 @@ class code_formatter(object, metaclass=code_formatter_meta):
frame = inspect.currentframe().f_back frame = inspect.currentframe().f_back
l = lookup(self, frame, *args, **kwargs) l = lookup(self, frame, *args, **kwargs)
def convert(match): def convert(match):
ident = match.group('lone') ident = match.group("lone")
# check for a lone identifier # check for a lone identifier
if ident: if ident:
indent = match.group('indent') # must be spaces indent = match.group("indent") # must be spaces
lone = '%s' % (l[ident], ) lone = "%s" % (l[ident],)
def indent_lines(gen): def indent_lines(gen):
for line in gen: for line in gen:
yield indent yield indent
yield line yield line
return ''.join(indent_lines(lone.splitlines(True)))
return "".join(indent_lines(lone.splitlines(True)))
# check for an identifier, braced or not # check for an identifier, braced or not
ident = match.group('ident') or match.group('b_ident') ident = match.group("ident") or match.group("b_ident")
if ident is not None: if ident is not None:
return '%s' % (l[ident], ) return "%s" % (l[ident],)
# check for a positional parameter, braced or not # check for a positional parameter, braced or not
pos = match.group('pos') or match.group('b_pos') pos = match.group("pos") or match.group("b_pos")
if pos is not None: if pos is not None:
pos = int(pos) pos = int(pos)
if pos > len(args): if pos > len(args):
raise ValueError \ raise ValueError(
('Positional parameter #%d not found in pattern' % pos, "Positional parameter #%d not found in pattern" % pos,
code_formatter.pattern) code_formatter.pattern,
return '%s' % (args[int(pos)], ) )
return "%s" % (args[int(pos)],)
# check for a double braced expression # check for a double braced expression
eval_expr = match.group('eval') eval_expr = match.group("eval")
if eval_expr is not None: if eval_expr is not None:
result = eval(eval_expr, {}, l) result = eval(eval_expr, {}, l)
return '%s' % (result, ) return "%s" % (result,)
# check for an escaped delimiter # check for an escaped delimiter
if match.group('escaped') is not None: if match.group("escaped") is not None:
return '$' return "$"
# At this point, we have to match invalid # At this point, we have to match invalid
if match.group('invalid') is None: if match.group("invalid") is None:
# didn't match invalid! # didn't match invalid!
raise ValueError('Unrecognized named group in pattern', raise ValueError(
code_formatter.pattern) "Unrecognized named group in pattern",
code_formatter.pattern,
)
i = match.start('invalid') i = match.start("invalid")
if i == 0: if i == 0:
colno = 1 colno = 1
lineno = 1 lineno = 1
@@ -307,52 +324,64 @@ class code_formatter(object, metaclass=code_formatter_meta):
colno = i - sum(len(z) for z in lines) colno = i - sum(len(z) for z in lines)
lineno = len(lines) lineno = len(lines)
raise ValueError('Invalid format string: line %d, col %d' % raise ValueError(
(lineno, colno)) "Invalid format string: line %d, col %d" % (lineno, colno)
)
d = code_formatter.pattern.sub(convert, format) d = code_formatter.pattern.sub(convert, format)
self._append(d) self._append(d)
__all__ = [ "code_formatter" ]
if __name__ == '__main__': __all__ = ["code_formatter"]
if __name__ == "__main__":
from .code_formatter import code_formatter from .code_formatter import code_formatter
f = code_formatter() f = code_formatter()
class Foo(dict): class Foo(dict):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.update(kwargs) self.update(kwargs)
def __getattr__(self, attr): def __getattr__(self, attr):
return self[attr] return self[attr]
x = "this is a test" x = "this is a test"
l = [ [Foo(x=[Foo(y=9)])] ] l = [[Foo(x=[Foo(y=9)])]]
y = code_formatter() y = code_formatter()
y(''' y(
"""
{ {
this_is_a_test(); this_is_a_test();
} }
''') """
f(' $y') )
f('''$__file__:$__line__ f(" $y")
{''') f(
"""$__file__:$__line__
{"""
)
f("${{', '.join(str(x) for x in range(4))}}") f("${{', '.join(str(x) for x in range(4))}}")
f('${x}') f("${x}")
f('$x') f("$x")
f.indent() f.indent()
for i in range(5): for i in range(5):
f('$x') f("$x")
f('$i') f("$i")
f('$0', "zero") f("$0", "zero")
f('$1 $0', "zero", "one") f("$1 $0", "zero", "one")
f('${0}', "he went") f("${0}", "he went")
f('${0}asdf', "he went") f("${0}asdf", "he went")
f.dedent() f.dedent()
f(''' f(
"""
${{l[0][0]["x"][0].y}} ${{l[0][0]["x"][0].y}}
} }
''', 1, 9) """,
1,
9,
)
print(f, end=' ') print(f, end=" ")

View File

@@ -46,8 +46,8 @@ import importer
from code_formatter import code_formatter from code_formatter import code_formatter
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('modpath', help='module the simobject belongs to') parser.add_argument("modpath", help="module the simobject belongs to")
parser.add_argument('cxx_config_cc', help='cxx config cc file to generate') parser.add_argument("cxx_config_cc", help="cxx config cc file to generate")
args = parser.parse_args() args = parser.parse_args()
@@ -63,22 +63,25 @@ import m5.params
code = code_formatter() code = code_formatter()
entry_class = 'CxxConfigDirectoryEntry_%s' % sim_object_name entry_class = "CxxConfigDirectoryEntry_%s" % sim_object_name
param_class = '%sCxxConfigParams' % sim_object_name param_class = "%sCxxConfigParams" % sim_object_name
def cxx_bool(b): def cxx_bool(b):
return 'true' if b else 'false' return "true" if b else "false"
code('#include "params/%s.hh"' % sim_object_name) code('#include "params/%s.hh"' % sim_object_name)
for param in sim_object._params.values(): for param in sim_object._params.values():
if isSimObjectClass(param.ptype): if isSimObjectClass(param.ptype):
code('#include "%s"' % param.ptype._value_dict['cxx_header']) code('#include "%s"' % param.ptype._value_dict["cxx_header"])
code('#include "params/%s.hh"' % param.ptype.__name__) code('#include "params/%s.hh"' % param.ptype.__name__)
else: else:
param.ptype.cxx_ini_predecls(code) param.ptype.cxx_ini_predecls(code)
code('''#include "${{sim_object._value_dict['cxx_header']}}" code(
"""#include "${{sim_object._value_dict['cxx_header']}}"
#include "base/str.hh" #include "base/str.hh"
#include "cxx_config/${sim_object_name}.hh" #include "cxx_config/${sim_object_name}.hh"
@@ -87,34 +90,39 @@ namespace gem5
${param_class}::DirectoryEntry::DirectoryEntry() ${param_class}::DirectoryEntry::DirectoryEntry()
{ {
''') """
)
code.indent() code.indent()
for param in sim_object._params.values(): for param in sim_object._params.values():
is_vector = isinstance(param, m5.params.VectorParamDesc) is_vector = isinstance(param, m5.params.VectorParamDesc)
is_simobj = issubclass(param.ptype, m5.SimObject.SimObject) is_simobj = issubclass(param.ptype, m5.SimObject.SimObject)
code('parameters["%s"] = new ParamDesc("%s", %s, %s);' % code(
(param.name, param.name, cxx_bool(is_vector), 'parameters["%s"] = new ParamDesc("%s", %s, %s);'
cxx_bool(is_simobj))); % (param.name, param.name, cxx_bool(is_vector), cxx_bool(is_simobj))
)
for port in sim_object._ports.values(): for port in sim_object._ports.values():
is_vector = isinstance(port, m5.params.VectorPort) is_vector = isinstance(port, m5.params.VectorPort)
is_requestor = port.role == 'GEM5 REQUESTOR' is_requestor = port.role == "GEM5 REQUESTOR"
code('ports["%s"] = new PortDesc("%s", %s, %s);' % code(
(port.name, port.name, cxx_bool(is_vector), 'ports["%s"] = new PortDesc("%s", %s, %s);'
cxx_bool(is_requestor))) % (port.name, port.name, cxx_bool(is_vector), cxx_bool(is_requestor))
)
code.dedent() code.dedent()
code('''} code(
"""}
bool bool
${param_class}::setSimObject(const std::string &name, SimObject *simObject) ${param_class}::setSimObject(const std::string &name, SimObject *simObject)
{ {
bool ret = true; bool ret = true;
if (false) { if (false) {
''') """
)
code.indent() code.indent()
for param in sim_object._params.values(): for param in sim_object._params.values():
@@ -124,14 +132,17 @@ for param in sim_object._params.values():
if is_simobj and not is_vector: if is_simobj and not is_vector:
code('} else if (name == "${{param.name}}") {') code('} else if (name == "${{param.name}}") {')
code.indent() code.indent()
code('this->${{param.name}} = ' code(
'dynamic_cast<${{param.ptype.cxx_type}}>(simObject);') "this->${{param.name}} = "
code('if (simObject && !this->${{param.name}})') "dynamic_cast<${{param.ptype.cxx_type}}>(simObject);"
code(' ret = false;') )
code("if (simObject && !this->${{param.name}})")
code(" ret = false;")
code.dedent() code.dedent()
code.dedent() code.dedent()
code(''' code(
"""
} else { } else {
ret = false; ret = false;
} }
@@ -146,7 +157,8 @@ ${param_class}::setSimObjectVector(const std::string &name,
bool ret = true; bool ret = true;
if (false) { if (false) {
''') """
)
code.indent() code.indent()
for param in sim_object._params.values(): for param in sim_object._params.values():
@@ -156,23 +168,28 @@ for param in sim_object._params.values():
if is_simobj and is_vector: if is_simobj and is_vector:
code('} else if (name == "${{param.name}}") {') code('} else if (name == "${{param.name}}") {')
code.indent() code.indent()
code('this->${{param.name}}.clear();') code("this->${{param.name}}.clear();")
code('for (auto i = simObjects.begin(); ' code(
'ret && i != simObjects.end(); i ++)') "for (auto i = simObjects.begin(); "
code('{') "ret && i != simObjects.end(); i ++)"
)
code("{")
code.indent() code.indent()
code('${{param.ptype.cxx_type}} object = ' code(
'dynamic_cast<${{param.ptype.cxx_type}}>(*i);') "${{param.ptype.cxx_type}} object = "
code('if (*i && !object)') "dynamic_cast<${{param.ptype.cxx_type}}>(*i);"
code(' ret = false;') )
code('else') code("if (*i && !object)")
code(' this->${{param.name}}.push_back(object);') code(" ret = false;")
code("else")
code(" this->${{param.name}}.push_back(object);")
code.dedent() code.dedent()
code('}') code("}")
code.dedent() code.dedent()
code.dedent() code.dedent()
code(''' code(
"""
} else { } else {
ret = false; ret = false;
} }
@@ -193,7 +210,8 @@ ${param_class}::setParam(const std::string &name,
bool ret = true; bool ret = true;
if (false) { if (false) {
''') """
)
code.indent() code.indent()
for param in sim_object._params.values(): for param in sim_object._params.values():
@@ -203,12 +221,14 @@ for param in sim_object._params.values():
if not is_simobj and not is_vector: if not is_simobj and not is_vector:
code('} else if (name == "${{param.name}}") {') code('} else if (name == "${{param.name}}") {')
code.indent() code.indent()
param.ptype.cxx_ini_parse(code, param.ptype.cxx_ini_parse(
'value', 'this->%s' % param.name, 'ret =') code, "value", "this->%s" % param.name, "ret ="
)
code.dedent() code.dedent()
code.dedent() code.dedent()
code(''' code(
"""
} else { } else {
ret = false; ret = false;
} }
@@ -223,7 +243,8 @@ ${param_class}::setParamVector(const std::string &name,
bool ret = true; bool ret = true;
if (false) { if (false) {
''') """
)
code.indent() code.indent()
for param in sim_object._params.values(): for param in sim_object._params.values():
@@ -233,22 +254,23 @@ for param in sim_object._params.values():
if not is_simobj and is_vector: if not is_simobj and is_vector:
code('} else if (name == "${{param.name}}") {') code('} else if (name == "${{param.name}}") {')
code.indent() code.indent()
code('${{param.name}}.clear();') code("${{param.name}}.clear();")
code('for (auto i = values.begin(); ' code(
'ret && i != values.end(); i ++)') "for (auto i = values.begin(); " "ret && i != values.end(); i ++)"
code('{') )
code("{")
code.indent() code.indent()
code('${{param.ptype.cxx_type}} elem;') code("${{param.ptype.cxx_type}} elem;")
param.ptype.cxx_ini_parse(code, param.ptype.cxx_ini_parse(code, "*i", "elem", "ret =")
'*i', 'elem', 'ret =') code("if (ret)")
code('if (ret)') code(" this->${{param.name}}.push_back(elem);")
code(' this->${{param.name}}.push_back(elem);')
code.dedent() code.dedent()
code('}') code("}")
code.dedent() code.dedent()
code.dedent() code.dedent()
code(''' code(
"""
} else { } else {
ret = false; ret = false;
} }
@@ -263,15 +285,17 @@ ${param_class}::setPortConnectionCount(const std::string &name,
bool ret = true; bool ret = true;
if (false) { if (false) {
''') """
)
code.indent() code.indent()
for port in sim_object._ports.values(): for port in sim_object._ports.values():
code('} else if (name == "${{port.name}}") {') code('} else if (name == "${{port.name}}") {')
code(' this->port_${{port.name}}_connection_count = count;') code(" this->port_${{port.name}}_connection_count = count;")
code.dedent() code.dedent()
code(''' code(
"""
} else { } else {
ret = false; ret = false;
} }
@@ -282,18 +306,21 @@ code('''
SimObject * SimObject *
${param_class}::simObjectCreate() ${param_class}::simObjectCreate()
{ {
''') """
)
code.indent() code.indent()
if hasattr(sim_object, 'abstract') and sim_object.abstract: if hasattr(sim_object, "abstract") and sim_object.abstract:
code('return nullptr;') code("return nullptr;")
else: else:
code('return this->create();') code("return this->create();")
code.dedent() code.dedent()
code('''} code(
"""}
} // namespace gem5 } // namespace gem5
''') """
)
code.write(args.cxx_config_cc) code.write(args.cxx_config_cc)

View File

@@ -46,8 +46,8 @@ import importer
from code_formatter import code_formatter from code_formatter import code_formatter
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('modpath', help='module the simobject belongs to') parser.add_argument("modpath", help="module the simobject belongs to")
parser.add_argument('cxx_config_hh', help='cxx config header file to generate') parser.add_argument("cxx_config_hh", help="cxx config header file to generate")
args = parser.parse_args() args = parser.parse_args()
@@ -60,10 +60,11 @@ sim_object = getattr(module, sim_object_name)
code = code_formatter() code = code_formatter()
entry_class = 'CxxConfigDirectoryEntry_%s' % sim_object_name entry_class = "CxxConfigDirectoryEntry_%s" % sim_object_name
param_class = '%sCxxConfigParams' % sim_object_name param_class = "%sCxxConfigParams" % sim_object_name
code('''#include "params/${sim_object_name}.hh" code(
"""#include "params/${sim_object_name}.hh"
#include "sim/cxx_config.hh" #include "sim/cxx_config.hh"
@@ -110,6 +111,7 @@ class ${param_class} : public CxxConfigParams, public ${sim_object_name}Params
}; };
} // namespace gem5 } // namespace gem5
''') """
)
code.write(args.cxx_config_hh) code.write(args.cxx_config_hh)

View File

@@ -44,35 +44,41 @@ parser = argparse.ArgumentParser()
parser.add_argument("hh", help="the path of the debug flag header file") parser.add_argument("hh", help="the path of the debug flag header file")
parser.add_argument("name", help="the name of the debug flag") parser.add_argument("name", help="the name of the debug flag")
parser.add_argument("desc", help="a description of the debug flag") parser.add_argument("desc", help="a description of the debug flag")
parser.add_argument("fmt", parser.add_argument(
help="whether the flag is a format flag (True or False)") "fmt", help="whether the flag is a format flag (True or False)"
parser.add_argument("components", )
help="components of a compound flag, if applicable, joined with :") parser.add_argument(
"components",
help="components of a compound flag, if applicable, joined with :",
)
args = parser.parse_args() args = parser.parse_args()
fmt = args.fmt.lower() fmt = args.fmt.lower()
if fmt == 'true': if fmt == "true":
fmt = True fmt = True
elif fmt == 'false': elif fmt == "false":
fmt = False fmt = False
else: else:
print(f'Unrecognized "FMT" value {fmt}', file=sys.stderr) print(f'Unrecognized "FMT" value {fmt}', file=sys.stderr)
sys.exit(1) sys.exit(1)
components = args.components.split(':') if args.components else [] components = args.components.split(":") if args.components else []
code = code_formatter() code = code_formatter()
code(''' code(
"""
#ifndef __DEBUG_${{args.name}}_HH__ #ifndef __DEBUG_${{args.name}}_HH__
#define __DEBUG_${{args.name}}_HH__ #define __DEBUG_${{args.name}}_HH__
#include "base/compiler.hh" // For namespace deprecation #include "base/compiler.hh" // For namespace deprecation
#include "base/debug.hh" #include "base/debug.hh"
''') """
)
for flag in components: for flag in components:
code('#include "debug/${flag}.hh"') code('#include "debug/${flag}.hh"')
code(''' code(
"""
namespace gem5 namespace gem5
{ {
@@ -82,14 +88,16 @@ namespace debug
namespace unions namespace unions
{ {
''') """
)
# Use unions to prevent debug flags from being destructed. It's the # Use unions to prevent debug flags from being destructed. It's the
# responsibility of the programmer to handle object destruction for members # responsibility of the programmer to handle object destruction for members
# of the union. We purposefully leave that destructor empty so that we can # of the union. We purposefully leave that destructor empty so that we can
# use debug flags even in the destructors of other objects. # use debug flags even in the destructors of other objects.
if components: if components:
code(''' code(
"""
inline union ${{args.name}} inline union ${{args.name}}
{ {
~${{args.name}}() {} ~${{args.name}}() {}
@@ -100,9 +108,11 @@ inline union ${{args.name}}
} }
}; };
} ${{args.name}}; } ${{args.name}};
''') """
)
else: else:
code(''' code(
"""
inline union ${{args.name}} inline union ${{args.name}}
{ {
~${{args.name}}() {} ~${{args.name}}() {}
@@ -110,18 +120,21 @@ inline union ${{args.name}}
"${{args.name}}", "${{args.desc}}", ${{"true" if fmt else "false"}} "${{args.name}}", "${{args.desc}}", ${{"true" if fmt else "false"}}
}; };
} ${{args.name}}; } ${{args.name}};
''') """
)
code(''' code(
"""
} // namespace unions } // namespace unions
inline constexpr const auto& ${{args.name}} = inline constexpr const auto& ${{args.name}} =
::gem5::debug::unions::${{args.name}}.${{args.name}}; ::gem5::debug::unions::${{args.name}}.${{args.name}};
} // namespace debug } // namespace debug
} // namespace gem5 } // namespace gem5
#endif // __DEBUG_${{args.name}}_HH__ #endif // __DEBUG_${{args.name}}_HH__
''') """
)
code.write(args.hh) code.write(args.hh)

View File

@@ -46,17 +46,18 @@ import importer
from code_formatter import code_formatter from code_formatter import code_formatter
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('modpath', help='module the enum belongs to') parser.add_argument("modpath", help="module the enum belongs to")
parser.add_argument('enum_cc', help='enum cc file to generate') parser.add_argument("enum_cc", help="enum cc file to generate")
parser.add_argument('use_python', parser.add_argument(
help='whether python is enabled in gem5 (True or False)') "use_python", help="whether python is enabled in gem5 (True or False)"
)
args = parser.parse_args() args = parser.parse_args()
use_python = args.use_python.lower() use_python = args.use_python.lower()
if use_python == 'true': if use_python == "true":
use_python = True use_python = True
elif use_python == 'false': elif use_python == "false":
use_python = False use_python = False
else: else:
print(f'Unrecognized "use_python" value {use_python}', file=sys.stderr) print(f'Unrecognized "use_python" value {use_python}', file=sys.stderr)
@@ -75,41 +76,46 @@ wrapper_name = enum.wrapper_name
file_name = enum.__name__ file_name = enum.__name__
name = enum.__name__ if enum.enum_name is None else enum.enum_name name = enum.__name__ if enum.enum_name is None else enum.enum_name
code('''#include "base/compiler.hh" code(
"""#include "base/compiler.hh"
#include "enums/$file_name.hh" #include "enums/$file_name.hh"
namespace gem5 namespace gem5
{ {
''') """
)
if enum.wrapper_is_struct: if enum.wrapper_is_struct:
code('const char *${wrapper_name}::${name}Strings' code("const char *${wrapper_name}::${name}Strings" "[Num_${name}] =")
'[Num_${name}] =')
else: else:
if enum.is_class: if enum.is_class:
code('''\ code(
"""\
const char *${name}Strings[static_cast<int>(${name}::Num_${name})] = const char *${name}Strings[static_cast<int>(${name}::Num_${name})] =
''') """
)
else: else:
code('''GEM5_DEPRECATED_NAMESPACE(Enums, enums); code(
"""GEM5_DEPRECATED_NAMESPACE(Enums, enums);
namespace enums namespace enums
{''') {"""
)
code.indent(1) code.indent(1)
code('const char *${name}Strings[Num_${name}] =') code("const char *${name}Strings[Num_${name}] =")
code('{') code("{")
code.indent(1) code.indent(1)
for val in enum.vals: for val in enum.vals:
code('"$val",') code('"$val",')
code.dedent(1) code.dedent(1)
code('};') code("};")
if not enum.wrapper_is_struct and not enum.is_class: if not enum.wrapper_is_struct and not enum.is_class:
code.dedent(1) code.dedent(1)
code('} // namespace enums') code("} // namespace enums")
code('} // namespace gem5') code("} // namespace gem5")
if use_python: if use_python:
@@ -118,7 +124,8 @@ if use_python:
enum_name = enum.__name__ if enum.enum_name is None else enum.enum_name enum_name = enum.__name__ if enum.enum_name is None else enum.enum_name
wrapper_name = enum_name if enum.is_class else enum.wrapper_name wrapper_name = enum_name if enum.is_class else enum.wrapper_name
code('''#include "pybind11/pybind11.h" code(
"""#include "pybind11/pybind11.h"
#include "pybind11/stl.h" #include "pybind11/stl.h"
#include <sim/init.hh> #include <sim/init.hh>
@@ -133,7 +140,8 @@ module_init(py::module_ &m_internal)
{ {
py::module_ m = m_internal.def_submodule("enum_${name}"); py::module_ m = m_internal.def_submodule("enum_${name}");
''') """
)
if enum.is_class: if enum.is_class:
code('py::enum_<${enum_name}>(m, "enum_${name}")') code('py::enum_<${enum_name}>(m, "enum_${name}")')
else: else:
@@ -145,16 +153,18 @@ module_init(py::module_ &m_internal)
code('.value("${val}", ${wrapper_name}::${val})') code('.value("${val}", ${wrapper_name}::${val})')
code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})') code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})')
if not enum.is_class: if not enum.is_class:
code('.export_values()') code(".export_values()")
code(';') code(";")
code.dedent() code.dedent()
code('}') code("}")
code.dedent() code.dedent()
code(''' code(
"""
static EmbeddedPyBind embed_enum("enum_${name}", module_init); static EmbeddedPyBind embed_enum("enum_${name}", module_init);
} // namespace gem5 } // namespace gem5
''') """
)
code.write(args.enum_cc) code.write(args.enum_cc)

View File

@@ -46,8 +46,8 @@ import importer
from code_formatter import code_formatter from code_formatter import code_formatter
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('modpath', help='module the enum belongs to') parser.add_argument("modpath", help="module the enum belongs to")
parser.add_argument('enum_hh', help='enum header file to generate') parser.add_argument("enum_hh", help="enum header file to generate")
args = parser.parse_args() args = parser.parse_args()
@@ -64,53 +64,61 @@ code = code_formatter()
# Note that we wrap the enum in a class/struct to act as a namespace, # Note that we wrap the enum in a class/struct to act as a namespace,
# so that the enum strings can be brief w/o worrying about collisions. # so that the enum strings can be brief w/o worrying about collisions.
wrapper_name = enum.wrapper_name wrapper_name = enum.wrapper_name
wrapper = 'struct' if enum.wrapper_is_struct else 'namespace' wrapper = "struct" if enum.wrapper_is_struct else "namespace"
name = enum.__name__ if enum.enum_name is None else enum.enum_name name = enum.__name__ if enum.enum_name is None else enum.enum_name
idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) idem_macro = "__ENUM__%s__%s__" % (wrapper_name, name)
code('''\ code(
"""\
#ifndef $idem_macro #ifndef $idem_macro
#define $idem_macro #define $idem_macro
namespace gem5 namespace gem5
{ {
''') """
)
if enum.is_class: if enum.is_class:
code('''\ code(
"""\
enum class $name enum class $name
{ {
''') """
)
else: else:
code('''\ code(
"""\
$wrapper $wrapper_name { $wrapper $wrapper_name {
enum $name enum $name
{ {
''') """
)
code.indent(1) code.indent(1)
code.indent(1) code.indent(1)
for val in enum.vals: for val in enum.vals:
code('$val = ${{enum.map[val]}},') code("$val = ${{enum.map[val]}},")
code('Num_$name = ${{len(enum.vals)}}') code("Num_$name = ${{len(enum.vals)}}")
code.dedent(1) code.dedent(1)
code('};') code("};")
if enum.is_class: if enum.is_class:
code('''\ code(
"""\
extern const char *${name}Strings[static_cast<int>(${name}::Num_${name})]; extern const char *${name}Strings[static_cast<int>(${name}::Num_${name})];
''') """
)
elif enum.wrapper_is_struct: elif enum.wrapper_is_struct:
code('static const char *${name}Strings[Num_${name}];') code("static const char *${name}Strings[Num_${name}];")
else: else:
code('extern const char *${name}Strings[Num_${name}];') code("extern const char *${name}Strings[Num_${name}];")
if not enum.is_class: if not enum.is_class:
code.dedent(1) code.dedent(1)
code('}; // $wrapper_name') code("}; // $wrapper_name")
code() code()
code('} // namespace gem5') code("} // namespace gem5")
code() code()
code('#endif // $idem_macro') code("#endif // $idem_macro")
code.write(args.enum_hh) code.write(args.enum_hh)

View File

@@ -29,73 +29,77 @@ import os
import ply.lex import ply.lex
import ply.yacc import ply.yacc
class ParseError(Exception): class ParseError(Exception):
def __init__(self, message, token=None): def __init__(self, message, token=None):
Exception.__init__(self, message) Exception.__init__(self, message)
self.token = token self.token = token
class Grammar(object): class Grammar(object):
def setupLexerFactory(self, **kwargs): def setupLexerFactory(self, **kwargs):
if 'module' in kwargs: if "module" in kwargs:
raise AttributeError("module is an illegal attribute") raise AttributeError("module is an illegal attribute")
self.lex_kwargs = kwargs self.lex_kwargs = kwargs
def setupParserFactory(self, **kwargs): def setupParserFactory(self, **kwargs):
if 'module' in kwargs: if "module" in kwargs:
raise AttributeError("module is an illegal attribute") raise AttributeError("module is an illegal attribute")
if 'output' in kwargs: if "output" in kwargs:
dir,tab = os.path.split(output) dir, tab = os.path.split(output)
if not tab.endswith('.py'): if not tab.endswith(".py"):
raise AttributeError('The output file must end with .py') raise AttributeError("The output file must end with .py")
kwargs['outputdir'] = dir kwargs["outputdir"] = dir
kwargs['tabmodule'] = tab[:-3] kwargs["tabmodule"] = tab[:-3]
self.yacc_kwargs = kwargs self.yacc_kwargs = kwargs
def __getattr__(self, attr): def __getattr__(self, attr):
if attr == 'lexers': if attr == "lexers":
self.lexers = [] self.lexers = []
return self.lexers return self.lexers
if attr == 'lex_kwargs': if attr == "lex_kwargs":
self.setupLexerFactory() self.setupLexerFactory()
return self.lex_kwargs return self.lex_kwargs
if attr == 'yacc_kwargs': if attr == "yacc_kwargs":
self.setupParserFactory() self.setupParserFactory()
return self.yacc_kwargs return self.yacc_kwargs
if attr == 'lex': if attr == "lex":
self.lex = ply.lex.lex(module=self, **self.lex_kwargs) self.lex = ply.lex.lex(module=self, **self.lex_kwargs)
return self.lex return self.lex
if attr == 'yacc': if attr == "yacc":
self.yacc = ply.yacc.yacc(module=self, **self.yacc_kwargs) self.yacc = ply.yacc.yacc(module=self, **self.yacc_kwargs)
return self.yacc return self.yacc
if attr == 'current_lexer': if attr == "current_lexer":
if not self.lexers: if not self.lexers:
return None return None
return self.lexers[-1][0] return self.lexers[-1][0]
if attr == 'current_source': if attr == "current_source":
if not self.lexers: if not self.lexers:
return '<none>' return "<none>"
return self.lexers[-1][1] return self.lexers[-1][1]
if attr == 'current_line': if attr == "current_line":
if not self.lexers: if not self.lexers:
return -1 return -1
return self.current_lexer.lineno return self.current_lexer.lineno
raise AttributeError( raise AttributeError(
"'%s' object has no attribute '%s'" % (type(self), attr)) "'%s' object has no attribute '%s'" % (type(self), attr)
)
def parse_string(self, data, source='<string>', debug=None, tracking=0): def parse_string(self, data, source="<string>", debug=None, tracking=0):
if not isinstance(data, str): if not isinstance(data, str):
raise AttributeError( raise AttributeError(
"argument must be a string, was '%s'" % type(f)) "argument must be a string, was '%s'" % type(f)
)
lexer = self.lex.clone() lexer = self.lex.clone()
lexer.input(data) lexer.input(data)
@@ -114,24 +118,32 @@ class Grammar(object):
def parse_file(self, f, **kwargs): def parse_file(self, f, **kwargs):
if isinstance(f, str): if isinstance(f, str):
source = f source = f
f = open(f, 'r') f = open(f, "r")
elif isinstance(f, file): elif isinstance(f, file):
source = f.name source = f.name
else: else:
raise AttributeError( raise AttributeError(
"argument must be either a string or file, was '%s'" % type(f)) "argument must be either a string or file, was '%s'" % type(f)
)
return self.parse_string(f.read(), source, **kwargs) return self.parse_string(f.read(), source, **kwargs)
def p_error(self, t): def p_error(self, t):
if t: if t:
msg = "Syntax error at %s:%d:%d\n>>%s<<" % \ msg = "Syntax error at %s:%d:%d\n>>%s<<" % (
(self.current_source, t.lineno, t.lexpos + 1, t.value) self.current_source,
t.lineno,
t.lexpos + 1,
t.value,
)
else: else:
msg = "Syntax error at end of %s" % (self.current_source, ) msg = "Syntax error at end of %s" % (self.current_source,)
raise ParseError(msg, t) raise ParseError(msg, t)
def t_error(self, t): def t_error(self, t):
msg = "Illegal character %s @ %d:%d" % \ msg = "Illegal character %s @ %d:%d" % (
(repr(t.value[0]), t.lineno, t.lexpos) repr(t.value[0]),
t.lineno,
t.lexpos,
)
raise ParseError(msg, t) raise ParseError(msg, t)

View File

@@ -42,8 +42,8 @@ import sys
from code_formatter import code_formatter from code_formatter import code_formatter
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('info_py', help='info.py file path') parser.add_argument("info_py", help="info.py file path")
parser.add_argument('files', help='file to include in info.py', nargs='*') parser.add_argument("files", help="file to include in info.py", nargs="*")
args = parser.parse_args() args = parser.parse_args()
@@ -52,8 +52,8 @@ code = code_formatter()
for source in args.files: for source in args.files:
src = os.path.basename(source) src = os.path.basename(source)
with open(source, 'r') as f: with open(source, "r") as f:
data = ''.join(f) data = "".join(f)
code('${src} = ${{repr(data)}}') code("${src} = ${{repr(data)}}")
code.write(args.info_py) code.write(args.info_py)

View File

@@ -67,16 +67,17 @@ if len(sys.argv) < 4:
_, cpp, python, modpath, abspath = sys.argv _, cpp, python, modpath, abspath = sys.argv
with open(python, 'r') as f: with open(python, "r") as f:
src = f.read() src = f.read()
compiled = compile(src, python, 'exec') compiled = compile(src, python, "exec")
marshalled = marshal.dumps(compiled) marshalled = marshal.dumps(compiled)
compressed = zlib.compress(marshalled) compressed = zlib.compress(marshalled)
code = code_formatter() code = code_formatter()
code('''\ code(
"""\
#include "python/embedded.hh" #include "python/embedded.hh"
namespace gem5 namespace gem5
@@ -84,14 +85,16 @@ namespace gem5
namespace namespace
{ {
''') """
)
bytesToCppArray(code, 'embedded_module_data', compressed) bytesToCppArray(code, "embedded_module_data", compressed)
# The name of the EmbeddedPython object doesn't matter since it's in an # The name of the EmbeddedPython object doesn't matter since it's in an
# anonymous namespace, and it's constructor takes care of installing it into a # anonymous namespace, and it's constructor takes care of installing it into a
# global list. # global list.
code(''' code(
"""
EmbeddedPython embedded_module_info( EmbeddedPython embedded_module_info(
"${abspath}", "${abspath}",
"${modpath}", "${modpath}",
@@ -101,6 +104,7 @@ EmbeddedPython embedded_module_info(
} // anonymous namespace } // anonymous namespace
} // namespace gem5 } // namespace gem5
''') """
)
code.write(cpp) code.write(cpp)

View File

@@ -46,17 +46,18 @@ import importer
from code_formatter import code_formatter from code_formatter import code_formatter
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('modpath', help='module the simobject belongs to') parser.add_argument("modpath", help="module the simobject belongs to")
parser.add_argument('param_cc', help='parameter cc file to generate') parser.add_argument("param_cc", help="parameter cc file to generate")
parser.add_argument('use_python', parser.add_argument(
help='whether python is enabled in gem5 (True or False)') "use_python", help="whether python is enabled in gem5 (True or False)"
)
args = parser.parse_args() args = parser.parse_args()
use_python = args.use_python.lower() use_python = args.use_python.lower()
if use_python == 'true': if use_python == "true":
use_python = True use_python = True
elif use_python == 'false': elif use_python == "false":
use_python = False use_python = False
else: else:
print(f'Unrecognized "use_python" value {use_python}', file=sys.stderr) print(f'Unrecognized "use_python" value {use_python}', file=sys.stderr)
@@ -64,7 +65,7 @@ else:
basename = os.path.basename(args.param_cc) basename = os.path.basename(args.param_cc)
no_ext = os.path.splitext(basename)[0] no_ext = os.path.splitext(basename)[0]
sim_object_name = '_'.join(no_ext.split('_')[1:]) sim_object_name = "_".join(no_ext.split("_")[1:])
importer.install() importer.install()
module = importlib.import_module(args.modpath) module = importlib.import_module(args.modpath)
@@ -80,14 +81,16 @@ py_class_name = sim_object.pybind_class
# the object itself, not including inherited params (which # the object itself, not including inherited params (which
# will also be inherited from the base class's param struct # will also be inherited from the base class's param struct
# here). Sort the params based on their key # here). Sort the params based on their key
params = list(map(lambda k_v: k_v[1], params = list(
sorted(sim_object._params.local.items()))) map(lambda k_v: k_v[1], sorted(sim_object._params.local.items()))
)
ports = sim_object._ports.local ports = sim_object._ports.local
# only include pybind if python is enabled in the build # only include pybind if python is enabled in the build
if use_python: if use_python:
code('''#include "pybind11/pybind11.h" code(
"""#include "pybind11/pybind11.h"
#include "pybind11/stl.h" #include "pybind11/stl.h"
#include <type_traits> #include <type_traits>
@@ -99,9 +102,11 @@ if use_python:
#include "${{sim_object.cxx_header}}" #include "${{sim_object.cxx_header}}"
''') """
)
else: else:
code(''' code(
"""
#include <type_traits> #include <type_traits>
#include "base/compiler.hh" #include "base/compiler.hh"
@@ -109,13 +114,15 @@ else:
#include "${{sim_object.cxx_header}}" #include "${{sim_object.cxx_header}}"
''') """
)
# only include the python params code if python is enabled. # only include the python params code if python is enabled.
if use_python: if use_python:
for param in params: for param in params:
param.pybind_predecls(code) param.pybind_predecls(code)
code('''namespace py = pybind11; code(
"""namespace py = pybind11;
namespace gem5 namespace gem5
{ {
@@ -124,39 +131,48 @@ static void
module_init(py::module_ &m_internal) module_init(py::module_ &m_internal)
{ {
py::module_ m = m_internal.def_submodule("param_${sim_object}"); py::module_ m = m_internal.def_submodule("param_${sim_object}");
''') """
)
code.indent() code.indent()
if sim_object._base: if sim_object._base:
code('py::class_<${sim_object}Params, ' \ code(
'${{sim_object._base.type}}Params, ' \ "py::class_<${sim_object}Params, "
'std::unique_ptr<${{sim_object}}Params, py::nodelete>>(' \ "${{sim_object._base.type}}Params, "
'm, "${sim_object}Params")') "std::unique_ptr<${{sim_object}}Params, py::nodelete>>("
'm, "${sim_object}Params")'
)
else: else:
code('py::class_<${sim_object}Params, ' \ code(
'std::unique_ptr<${sim_object}Params, py::nodelete>>(' \ "py::class_<${sim_object}Params, "
'm, "${sim_object}Params")') "std::unique_ptr<${sim_object}Params, py::nodelete>>("
'm, "${sim_object}Params")'
)
code.indent() code.indent()
if not hasattr(sim_object, 'abstract') or not sim_object.abstract: if not hasattr(sim_object, "abstract") or not sim_object.abstract:
code('.def(py::init<>())') code(".def(py::init<>())")
code('.def("create", &${sim_object}Params::create)') code('.def("create", &${sim_object}Params::create)')
param_exports = sim_object.cxx_param_exports + [ param_exports = (
PyBindProperty(k) sim_object.cxx_param_exports
for k, v in sorted(sim_object._params.local.items()) + [
] + [ PyBindProperty(k)
PyBindProperty(f"port_{port.name}_connection_count") for k, v in sorted(sim_object._params.local.items())
for port in ports.values() ]
] + [
PyBindProperty(f"port_{port.name}_connection_count")
for port in ports.values()
]
)
for exp in param_exports: for exp in param_exports:
exp.export(code, f"{sim_object}Params") exp.export(code, f"{sim_object}Params")
code(';') code(";")
code() code()
code.dedent() code.dedent()
bases = [] bases = []
if 'cxx_base' in sim_object._value_dict: if "cxx_base" in sim_object._value_dict:
# If the c++ base class implied by python inheritance was # If the c++ base class implied by python inheritance was
# overridden, use that value. # overridden, use that value.
if sim_object.cxx_base: if sim_object.cxx_base:
@@ -170,32 +186,39 @@ py::module_ m = m_internal.def_submodule("param_${sim_object}");
if bases: if bases:
base_str = ", ".join(bases) base_str = ", ".join(bases)
code('py::class_<${{sim_object.cxx_class}}, ${base_str}, ' \ code(
'std::unique_ptr<${{sim_object.cxx_class}}, py::nodelete>>(' \ "py::class_<${{sim_object.cxx_class}}, ${base_str}, "
'm, "${py_class_name}")') "std::unique_ptr<${{sim_object.cxx_class}}, py::nodelete>>("
'm, "${py_class_name}")'
)
else: else:
code('py::class_<${{sim_object.cxx_class}}, ' \ code(
'std::unique_ptr<${{sim_object.cxx_class}}, py::nodelete>>(' \ "py::class_<${{sim_object.cxx_class}}, "
'm, "${py_class_name}")') "std::unique_ptr<${{sim_object.cxx_class}}, py::nodelete>>("
'm, "${py_class_name}")'
)
code.indent() code.indent()
for exp in sim_object.cxx_exports: for exp in sim_object.cxx_exports:
exp.export(code, sim_object.cxx_class) exp.export(code, sim_object.cxx_class)
code(';') code(";")
code.dedent() code.dedent()
code() code()
code.dedent() code.dedent()
code('}') code("}")
code() code()
code('static EmbeddedPyBind ' code(
'embed_obj("${0}", module_init, "${1}");', "static EmbeddedPyBind " 'embed_obj("${0}", module_init, "${1}");',
sim_object, sim_object._base.type if sim_object._base else "") sim_object,
sim_object._base.type if sim_object._base else "",
)
code() code()
code('} // namespace gem5') code("} // namespace gem5")
# include the create() methods whether or not python is enabled. # include the create() methods whether or not python is enabled.
if not hasattr(sim_object, 'abstract') or not sim_object.abstract: if not hasattr(sim_object, "abstract") or not sim_object.abstract:
if 'type' in sim_object.__dict__: if "type" in sim_object.__dict__:
code(''' code(
"""
namespace gem5 namespace gem5
{ {
@@ -268,6 +291,7 @@ Dummy${sim_object}Shunt<${{sim_object.cxx_class}}>::Params::create() const
} }
} // namespace gem5 } // namespace gem5
''') """
)
code.write(args.param_cc) code.write(args.param_cc)

View File

@@ -46,8 +46,8 @@ import importer
from code_formatter import code_formatter from code_formatter import code_formatter
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('modpath', help='module the simobject belongs to') parser.add_argument("modpath", help="module the simobject belongs to")
parser.add_argument('param_hh', help='parameter header file to generate') parser.add_argument("param_hh", help="parameter header file to generate")
args = parser.parse_args() args = parser.parse_args()
@@ -67,8 +67,9 @@ code = code_formatter()
# the object itself, not including inherited params (which # the object itself, not including inherited params (which
# will also be inherited from the base class's param struct # will also be inherited from the base class's param struct
# here). Sort the params based on their key # here). Sort the params based on their key
params = list(map(lambda k_v: k_v[1], params = list(
sorted(sim_object._params.local.items()))) map(lambda k_v: k_v[1], sorted(sim_object._params.local.items()))
)
ports = sim_object._ports.local ports = sim_object._ports.local
try: try:
ptypes = [p.ptype for p in params] ptypes = [p.ptype for p in params]
@@ -79,41 +80,44 @@ except:
warned_about_nested_templates = False warned_about_nested_templates = False
class CxxClass(object): class CxxClass(object):
def __init__(self, sig, template_params=[]): def __init__(self, sig, template_params=[]):
# Split the signature into its constituent parts. This could # Split the signature into its constituent parts. This could
# potentially be done with regular expressions, but # potentially be done with regular expressions, but
# it's simple enough to pick appart a class signature # it's simple enough to pick appart a class signature
# manually. # manually.
parts = sig.split('<', 1) parts = sig.split("<", 1)
base = parts[0] base = parts[0]
t_args = [] t_args = []
if len(parts) > 1: if len(parts) > 1:
# The signature had template arguments. # The signature had template arguments.
text = parts[1].rstrip(' \t\n>') text = parts[1].rstrip(" \t\n>")
arg = '' arg = ""
# Keep track of nesting to avoid splitting on ","s embedded # Keep track of nesting to avoid splitting on ","s embedded
# in the arguments themselves. # in the arguments themselves.
depth = 0 depth = 0
for c in text: for c in text:
if c == '<': if c == "<":
depth = depth + 1 depth = depth + 1
if depth > 0 and not warned_about_nested_templates: if depth > 0 and not warned_about_nested_templates:
warned_about_nested_templates = True warned_about_nested_templates = True
print('Nested template argument in cxx_class.' print(
' This feature is largely untested and ' "Nested template argument in cxx_class."
' may not work.') " This feature is largely untested and "
elif c == '>': " may not work."
)
elif c == ">":
depth = depth - 1 depth = depth - 1
elif c == ',' and depth == 0: elif c == "," and depth == 0:
t_args.append(arg.strip()) t_args.append(arg.strip())
arg = '' arg = ""
else: else:
arg = arg + c arg = arg + c
if arg: if arg:
t_args.append(arg.strip()) t_args.append(arg.strip())
# Split the non-template part on :: boundaries. # Split the non-template part on :: boundaries.
class_path = base.split('::') class_path = base.split("::")
# The namespaces are everything except the last part of the class path. # The namespaces are everything except the last part of the class path.
self.namespaces = class_path[:-1] self.namespaces = class_path[:-1]
@@ -125,7 +129,7 @@ class CxxClass(object):
# Iterate through the template arguments and their values. This # Iterate through the template arguments and their values. This
# will likely break if parameter packs are used. # will likely break if parameter packs are used.
for arg, param in zip(t_args, template_params): for arg, param in zip(t_args, template_params):
type_keys = ('class', 'typename') type_keys = ("class", "typename")
# If a parameter is a type, parse it recursively. Otherwise # If a parameter is a type, parse it recursively. Otherwise
# assume it's a constant, and store it verbatim. # assume it's a constant, and store it verbatim.
if any(param.strip().startswith(kw) for kw in type_keys): if any(param.strip().startswith(kw) for kw in type_keys):
@@ -140,21 +144,24 @@ class CxxClass(object):
arg.declare(code) arg.declare(code)
# Re-open the target namespace. # Re-open the target namespace.
for ns in self.namespaces: for ns in self.namespaces:
code('namespace $ns {') code("namespace $ns {")
# If this is a class template... # If this is a class template...
if self.template_params: if self.template_params:
code('template <${{", ".join(self.template_params)}}>') code('template <${{", ".join(self.template_params)}}>')
# The actual class declaration. # The actual class declaration.
code('class ${{self.name}};') code("class ${{self.name}};")
# Close the target namespaces. # Close the target namespaces.
for ns in reversed(self.namespaces): for ns in reversed(self.namespaces):
code('} // namespace $ns') code("} // namespace $ns")
code('''\
code(
"""\
#ifndef __PARAMS__${sim_object}__ #ifndef __PARAMS__${sim_object}__
#define __PARAMS__${sim_object}__ #define __PARAMS__${sim_object}__
''') """
)
# The base SimObject has a couple of params that get # The base SimObject has a couple of params that get
@@ -162,10 +169,12 @@ code('''\
# the normal Param mechanism; we slip them in here (needed # the normal Param mechanism; we slip them in here (needed
# predecls now, actual declarations below) # predecls now, actual declarations below)
if sim_object == SimObject: if sim_object == SimObject:
code('''#include <string>''') code("""#include <string>""")
cxx_class = CxxClass(sim_object._value_dict['cxx_class'], cxx_class = CxxClass(
sim_object._value_dict['cxx_template_params']) sim_object._value_dict["cxx_class"],
sim_object._value_dict["cxx_template_params"],
)
# A forward class declaration is sufficient since we are just # A forward class declaration is sufficient since we are just
# declaring a pointer. # declaring a pointer.
@@ -186,27 +195,29 @@ for ptype in ptypes:
code('#include "enums/${{ptype.__name__}}.hh"') code('#include "enums/${{ptype.__name__}}.hh"')
code() code()
code('namespace gem5') code("namespace gem5")
code('{') code("{")
code('') code("")
# now generate the actual param struct # now generate the actual param struct
code("struct ${sim_object}Params") code("struct ${sim_object}Params")
if sim_object._base: if sim_object._base:
code(" : public ${{sim_object._base.type}}Params") code(" : public ${{sim_object._base.type}}Params")
code("{") code("{")
if not hasattr(sim_object, 'abstract') or not sim_object.abstract: if not hasattr(sim_object, "abstract") or not sim_object.abstract:
if 'type' in sim_object.__dict__: if "type" in sim_object.__dict__:
code(" ${{sim_object.cxx_type}} create() const;") code(" ${{sim_object.cxx_type}} create() const;")
code.indent() code.indent()
if sim_object == SimObject: if sim_object == SimObject:
code(''' code(
"""
SimObjectParams() {} SimObjectParams() {}
virtual ~SimObjectParams() {} virtual ~SimObjectParams() {}
std::string name; std::string name;
''') """
)
for param in params: for param in params:
param.cxx_decl(code) param.cxx_decl(code)
@@ -214,11 +225,11 @@ for port in ports.values():
port.cxx_decl(code) port.cxx_decl(code)
code.dedent() code.dedent()
code('};') code("};")
code() code()
code('} // namespace gem5') code("} // namespace gem5")
code() code()
code('#endif // __PARAMS__${sim_object}__') code("#endif // __PARAMS__${sim_object}__")
code.write(args.param_hh) code.write(args.param_hh)

View File

@@ -50,7 +50,7 @@ from shutil import rmtree, copyfile
def hex_mask(terms): def hex_mask(terms):
dec_mask = reduce(operator.or_, [2 ** i for i in terms], 0) dec_mask = reduce(operator.or_, [2**i for i in terms], 0)
return "%08x" % dec_mask return "%08x" % dec_mask
@@ -66,7 +66,7 @@ def replace_tree(path):
def config_filesystem(system, options=None): def config_filesystem(system, options=None):
""" This function parses the system object to create the pseudo file system """This function parses the system object to create the pseudo file system
@param system: The system to create the config for @param system: The system to create the config for
@param options: An optional argument which contains an Options.py options @param options: An optional argument which contains an Options.py options
object. This is useful if when use se.py and will set the L2 cache object. This is useful if when use se.py and will set the L2 cache

View File

@@ -177,7 +177,7 @@ def config_mem(options, system):
from m5.util import fatal from m5.util import fatal
intlv_bits = int(math.log(nbr_mem_ctrls, 2)) intlv_bits = int(math.log(nbr_mem_ctrls, 2))
if 2 ** intlv_bits != nbr_mem_ctrls: if 2**intlv_bits != nbr_mem_ctrls:
fatal("Number of memory channels must be a power of 2") fatal("Number of memory channels must be a power of 2")
if opt_mem_type: if opt_mem_type:

View File

@@ -42,11 +42,11 @@ from textwrap import TextWrapper
class ObjectList(object): class ObjectList(object):
""" Creates a list of objects that are sub-classes of a given class. """ """Creates a list of objects that are sub-classes of a given class."""
def _is_obj_class(self, cls): def _is_obj_class(self, cls):
"""Determine if a class is a a sub class of the provided base class """Determine if a class is a a sub class of the provided base class
that can be instantiated. that can be instantiated.
""" """
# We can't use the normal inspect.isclass because the ParamFactory # We can't use the normal inspect.isclass because the ParamFactory
@@ -161,10 +161,10 @@ class CPUList(ObjectList):
class EnumList(ObjectList): class EnumList(ObjectList):
""" Creates a list of possible values for a given enum class. """ """Creates a list of possible values for a given enum class."""
def _add_objects(self): def _add_objects(self):
""" Add all enum values to the ObjectList """ """Add all enum values to the ObjectList"""
self._sub_classes = {} self._sub_classes = {}
for (key, value) in list(self.base_cls.__members__.items()): for (key, value) in list(self.base_cls.__members__.items()):
# All Enums have a value Num_NAME at the end which we # All Enums have a value Num_NAME at the end which we

View File

@@ -46,8 +46,7 @@ parser = ArgumentParser()
def add_option(*args, **kwargs): def add_option(*args, **kwargs):
"""Call "add_option" to the global options parser """Call "add_option" to the global options parser"""
"""
if called_parse_args: if called_parse_args:
m5.fatal("Can't add an option after calling SimpleOpts.parse_args") m5.fatal("Can't add an option after calling SimpleOpts.parse_args")

33
configs/dist/sw.py vendored
View File

@@ -35,33 +35,39 @@ from m5.defines import buildEnv
from m5.objects import * from m5.objects import *
from m5.util import addToPath, fatal from m5.util import addToPath, fatal
addToPath('../') addToPath("../")
from common import Simulation from common import Simulation
from common import Options from common import Options
def build_switch(args): def build_switch(args):
# instantiate an EtherSwitch # instantiate an EtherSwitch
switch = EtherSwitch() switch = EtherSwitch()
# instantiate distEtherLinks to connect switch ports # instantiate distEtherLinks to connect switch ports
# to other gem5 instances # to other gem5 instances
switch.portlink = [DistEtherLink(speed = args.ethernet_linkspeed, switch.portlink = [
delay = args.ethernet_linkdelay, DistEtherLink(
dist_rank = args.dist_rank, speed=args.ethernet_linkspeed,
dist_size = args.dist_size, delay=args.ethernet_linkdelay,
server_name = args.dist_server_name, dist_rank=args.dist_rank,
server_port = args.dist_server_port, dist_size=args.dist_size,
sync_start = args.dist_sync_start, server_name=args.dist_server_name,
sync_repeat = args.dist_sync_repeat, server_port=args.dist_server_port,
is_switch = True, sync_start=args.dist_sync_start,
num_nodes = args.dist_size) sync_repeat=args.dist_sync_repeat,
for i in range(args.dist_size)] is_switch=True,
num_nodes=args.dist_size,
)
for i in range(args.dist_size)
]
for (i, link) in enumerate(switch.portlink): for (i, link) in enumerate(switch.portlink):
link.int0 = switch.interface[i] link.int0 = switch.interface[i]
return switch return switch
def main(): def main():
# Add options # Add options
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@@ -70,8 +76,9 @@ def main():
args = parser.parse_args() args = parser.parse_args()
system = build_switch(args) system = build_switch(args)
root = Root(full_system = True, system = system) root = Root(full_system=True, system=system)
Simulation.run(args, root, None, None) Simulation.run(args, root, None, None)
if __name__ == "__m5_main__": if __name__ == "__m5_main__":
main() main()

View File

@@ -74,7 +74,7 @@ def create_cow_image(name):
def create(args): def create(args):
""" Create and configure the system object. """ """Create and configure the system object."""
if args.readfile and not os.path.isfile(args.readfile): if args.readfile and not os.path.isfile(args.readfile):
print("Error: Bootscript %s does not exist" % args.readfile) print("Error: Bootscript %s does not exist" % args.readfile)

View File

@@ -97,7 +97,7 @@ def config_ruby(system, args):
def create(args): def create(args):
""" Create and configure the system object. """ """Create and configure the system object."""
if args.script and not os.path.isfile(args.script): if args.script and not os.path.isfile(args.script):
print("Error: Bootscript %s does not exist" % args.script) print("Error: Bootscript %s does not exist" % args.script)

View File

@@ -85,7 +85,7 @@ def create_cow_image(name):
def create(args): def create(args):
""" Create and configure the system object. """ """Create and configure the system object."""
if args.script and not os.path.isfile(args.script): if args.script and not os.path.isfile(args.script):
print("Error: Bootscript %s does not exist" % args.script) print("Error: Bootscript %s does not exist" % args.script)

View File

@@ -142,7 +142,7 @@ def get_processes(cmd):
def create(args): def create(args):
""" Create and configure the system object. """ """Create and configure the system object."""
system = SimpleSeSystem(args) system = SimpleSeSystem(args)

View File

@@ -44,7 +44,7 @@ from common.SysPaths import binary, disk
class ArmBaremetal(ArmFsWorkload): class ArmBaremetal(ArmFsWorkload):
""" Baremetal workload """ """Baremetal workload"""
dtb_addr = 0 dtb_addr = 0

View File

@@ -92,7 +92,7 @@ board.set_se_binary_workload(
) )
# Lastly we run the simulation. # Lastly we run the simulation.
max_ticks = 10 ** 6 max_ticks = 10**6
simulator = Simulator(board=board, full_system=False) simulator = Simulator(board=board, full_system=False)
simulator.run(max_ticks=max_ticks) simulator.run(max_ticks=max_ticks)

View File

@@ -41,4 +41,4 @@ m5term localhost 3456
``` ```
This should allow you to run busybox, in which you can see the LupIO device at This should allow you to run busybox, in which you can see the LupIO device at
work! work!

View File

@@ -64,7 +64,7 @@ class L1Cache(Cache):
def connectCPU(self, cpu): def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port """Connect this cache's port to a CPU-side port
This must be defined in a subclass""" This must be defined in a subclass"""
raise NotImplementedError raise NotImplementedError

View File

@@ -52,9 +52,9 @@ class MyCacheSystem(RubySystem):
def setup(self, system, cpus, mem_ctrls): def setup(self, system, cpus, mem_ctrls):
"""Set up the Ruby cache subsystem. Note: This can't be done in the """Set up the Ruby cache subsystem. Note: This can't be done in the
constructor because many of these items require a pointer to the constructor because many of these items require a pointer to the
ruby system (self). This causes infinite recursion in initialize() ruby system (self). This causes infinite recursion in initialize()
if we do this in the __init__. if we do this in the __init__.
""" """
# Ruby's global network. # Ruby's global network.
self.network = MyNetwork(self) self.network = MyNetwork(self)
@@ -120,7 +120,7 @@ class L1Cache(L1Cache_Controller):
def __init__(self, system, ruby_system, cpu): def __init__(self, system, ruby_system, cpu):
"""CPUs are needed to grab the clock domain and system is needed for """CPUs are needed to grab the clock domain and system is needed for
the cache block size. the cache block size.
""" """
super(L1Cache, self).__init__() super(L1Cache, self).__init__()
@@ -136,24 +136,23 @@ class L1Cache(L1Cache_Controller):
def getBlockSizeBits(self, system): def getBlockSizeBits(self, system):
bits = int(math.log(system.cache_line_size, 2)) bits = int(math.log(system.cache_line_size, 2))
if 2 ** bits != system.cache_line_size.value: if 2**bits != system.cache_line_size.value:
panic("Cache line size not a power of 2!") panic("Cache line size not a power of 2!")
return bits return bits
def sendEvicts(self, cpu): def sendEvicts(self, cpu):
"""True if the CPU model or ISA requires sending evictions from caches """True if the CPU model or ISA requires sending evictions from caches
to the CPU. Two scenarios warrant forwarding evictions to the CPU: to the CPU. Two scenarios warrant forwarding evictions to the CPU:
1. The O3 model must keep the LSQ coherent with the caches 1. The O3 model must keep the LSQ coherent with the caches
2. The x86 mwait instruction is built on top of coherence 2. The x86 mwait instruction is built on top of coherence
3. The local exclusive monitor in ARM systems 3. The local exclusive monitor in ARM systems
""" """
if type(cpu) is DerivO3CPU or buildEnv["TARGET_ISA"] in ("x86", "arm"): if type(cpu) is DerivO3CPU or buildEnv["TARGET_ISA"] in ("x86", "arm"):
return True return True
return False return False
def connectQueues(self, ruby_system): def connectQueues(self, ruby_system):
"""Connect all of the queues for this controller. """Connect all of the queues for this controller."""
"""
# mandatoryQueue is a special variable. It is used by the sequencer to # mandatoryQueue is a special variable. It is used by the sequencer to
# send RubyRequests from the CPU (or other processor). It isn't # send RubyRequests from the CPU (or other processor). It isn't
# explicitly connected to anything. # explicitly connected to anything.
@@ -184,8 +183,7 @@ class DirController(Directory_Controller):
return cls._version - 1 return cls._version - 1
def __init__(self, ruby_system, ranges, mem_ctrls): def __init__(self, ruby_system, ranges, mem_ctrls):
"""ranges are the memory ranges assigned to this controller. """ranges are the memory ranges assigned to this controller."""
"""
if len(mem_ctrls) > 1: if len(mem_ctrls) > 1:
panic("This cache system can only be connected to one mem ctrl") panic("This cache system can only be connected to one mem ctrl")
super(DirController, self).__init__() super(DirController, self).__init__()
@@ -217,8 +215,7 @@ class DirController(Directory_Controller):
class MyNetwork(SimpleNetwork): class MyNetwork(SimpleNetwork):
"""A simple point-to-point network. This doesn't not use garnet. """A simple point-to-point network. This doesn't not use garnet."""
"""
def __init__(self, ruby_system): def __init__(self, ruby_system):
super(MyNetwork, self).__init__() super(MyNetwork, self).__init__()
@@ -227,7 +224,7 @@ class MyNetwork(SimpleNetwork):
def connectControllers(self, controllers): def connectControllers(self, controllers):
"""Connect all of the controllers to routers and connec the routers """Connect all of the controllers to routers and connec the routers
together in a point-to-point network. together in a point-to-point network.
""" """
# Create one router/switch per controller in the system # Create one router/switch per controller in the system
self.routers = [Switch(router_id=i) for i in range(len(controllers))] self.routers = [Switch(router_id=i) for i in range(len(controllers))]

View File

@@ -54,9 +54,9 @@ class MyCacheSystem(RubySystem):
def setup(self, system, cpus, mem_ctrls): def setup(self, system, cpus, mem_ctrls):
"""Set up the Ruby cache subsystem. Note: This can't be done in the """Set up the Ruby cache subsystem. Note: This can't be done in the
constructor because many of these items require a pointer to the constructor because many of these items require a pointer to the
ruby system (self). This causes infinite recursion in initialize() ruby system (self). This causes infinite recursion in initialize()
if we do this in the __init__. if we do this in the __init__.
""" """
# Ruby's global network. # Ruby's global network.
self.network = MyNetwork(self) self.network = MyNetwork(self)
@@ -118,7 +118,7 @@ class L1Cache(L1Cache_Controller):
def __init__(self, system, ruby_system, cpu): def __init__(self, system, ruby_system, cpu):
"""CPUs are needed to grab the clock domain and system is needed for """CPUs are needed to grab the clock domain and system is needed for
the cache block size. the cache block size.
""" """
super(L1Cache, self).__init__() super(L1Cache, self).__init__()
@@ -134,24 +134,23 @@ class L1Cache(L1Cache_Controller):
def getBlockSizeBits(self, system): def getBlockSizeBits(self, system):
bits = int(math.log(system.cache_line_size, 2)) bits = int(math.log(system.cache_line_size, 2))
if 2 ** bits != system.cache_line_size.value: if 2**bits != system.cache_line_size.value:
panic("Cache line size not a power of 2!") panic("Cache line size not a power of 2!")
return bits return bits
def sendEvicts(self, cpu): def sendEvicts(self, cpu):
"""True if the CPU model or ISA requires sending evictions from caches """True if the CPU model or ISA requires sending evictions from caches
to the CPU. Two scenarios warrant forwarding evictions to the CPU: to the CPU. Two scenarios warrant forwarding evictions to the CPU:
1. The O3 model must keep the LSQ coherent with the caches 1. The O3 model must keep the LSQ coherent with the caches
2. The x86 mwait instruction is built on top of coherence 2. The x86 mwait instruction is built on top of coherence
3. The local exclusive monitor in ARM systems 3. The local exclusive monitor in ARM systems
""" """
if type(cpu) is DerivO3CPU or buildEnv["TARGET_ISA"] in ("x86", "arm"): if type(cpu) is DerivO3CPU or buildEnv["TARGET_ISA"] in ("x86", "arm"):
return True return True
return False return False
def connectQueues(self, ruby_system): def connectQueues(self, ruby_system):
"""Connect all of the queues for this controller. """Connect all of the queues for this controller."""
"""
self.mandatoryQueue = MessageBuffer() self.mandatoryQueue = MessageBuffer()
self.requestFromCache = MessageBuffer(ordered=True) self.requestFromCache = MessageBuffer(ordered=True)
self.requestFromCache.out_port = ruby_system.network.in_port self.requestFromCache.out_port = ruby_system.network.in_port
@@ -173,8 +172,7 @@ class DirController(Directory_Controller):
return cls._version - 1 return cls._version - 1
def __init__(self, ruby_system, ranges, mem_ctrls): def __init__(self, ruby_system, ranges, mem_ctrls):
"""ranges are the memory ranges assigned to this controller. """ranges are the memory ranges assigned to this controller."""
"""
if len(mem_ctrls) > 1: if len(mem_ctrls) > 1:
panic("This cache system can only be connected to one mem ctrl") panic("This cache system can only be connected to one mem ctrl")
super(DirController, self).__init__() super(DirController, self).__init__()
@@ -203,8 +201,7 @@ class DirController(Directory_Controller):
class MyNetwork(SimpleNetwork): class MyNetwork(SimpleNetwork):
"""A simple point-to-point network. This doesn't not use garnet. """A simple point-to-point network. This doesn't not use garnet."""
"""
def __init__(self, ruby_system): def __init__(self, ruby_system):
super(MyNetwork, self).__init__() super(MyNetwork, self).__init__()
@@ -213,7 +210,7 @@ class MyNetwork(SimpleNetwork):
def connectControllers(self, controllers): def connectControllers(self, controllers):
"""Connect all of the controllers to routers and connec the routers """Connect all of the controllers to routers and connec the routers
together in a point-to-point network. together in a point-to-point network.
""" """
# Create one router/switch per controller in the system # Create one router/switch per controller in the system
self.routers = [Switch(router_id=i) for i in range(len(controllers))] self.routers = [Switch(router_id=i) for i in range(len(controllers))]

View File

@@ -52,11 +52,11 @@ class TestCacheSystem(RubySystem):
def setup(self, system, tester, mem_ctrls): def setup(self, system, tester, mem_ctrls):
"""Set up the Ruby cache subsystem. Note: This can't be done in the """Set up the Ruby cache subsystem. Note: This can't be done in the
constructor because many of these items require a pointer to the constructor because many of these items require a pointer to the
ruby system (self). This causes infinite recursion in initialize() ruby system (self). This causes infinite recursion in initialize()
if we do this in the __init__. if we do this in the __init__.
Setting up for running the RubyRandomTester is a little different Setting up for running the RubyRandomTester is a little different
than when we're using CPUs. than when we're using CPUs.
""" """
num_testers = tester.num_cpus num_testers = tester.num_cpus

View File

@@ -52,7 +52,7 @@ def define_options(parser):
def read_config_file(file): def read_config_file(file):
""" Read file as a module and return it """ """Read file as a module and return it"""
import types import types
import importlib.machinery import importlib.machinery

View File

@@ -200,10 +200,10 @@ def setup_memory_controllers(system, ruby, dir_cntrls, options):
def create_topology(controllers, options): def create_topology(controllers, options):
""" Called from create_system in configs/ruby/<protocol>.py """Called from create_system in configs/ruby/<protocol>.py
Must return an object which is a subclass of BaseTopology Must return an object which is a subclass of BaseTopology
found in configs/topologies/BaseTopology.py found in configs/topologies/BaseTopology.py
This is a wrapper for the legacy topologies. This is a wrapper for the legacy topologies.
""" """
exec("import topologies.%s as Topo" % options.topology) exec("import topologies.%s as Topo" % options.topology)
topology = eval("Topo.%s(controllers)" % options.topology) topology = eval("Topo.%s(controllers)" % options.topology)

View File

@@ -31,37 +31,37 @@ class BaseTopology(object):
description = "BaseTopology" description = "BaseTopology"
def __init__(self): def __init__(self):
""" When overriding place any objects created in """When overriding place any objects created in
configs/ruby/<protocol>.py that are needed in configs/ruby/<protocol>.py that are needed in
makeTopology (below) here. The minimum is usually makeTopology (below) here. The minimum is usually
all of the controllers created in the above file. all of the controllers created in the above file.
""" """
def makeTopology(self, options, network, IntLink, ExtLink, Router): def makeTopology(self, options, network, IntLink, ExtLink, Router):
""" Called from configs/ruby/Ruby.py """Called from configs/ruby/Ruby.py
The return value is ( list(Router), list(IntLink), list(ExtLink)) The return value is ( list(Router), list(IntLink), list(ExtLink))
The API of this function cannot change when subclassing!! The API of this function cannot change when subclassing!!
Any additional information needed to create this topology should Any additional information needed to create this topology should
be passed into the constructor when it's instantiated in be passed into the constructor when it's instantiated in
configs/ruby/<protocol>.py configs/ruby/<protocol>.py
""" """
m5.util.fatal("BaseTopology should have been overridden!!") m5.util.fatal("BaseTopology should have been overridden!!")
def registerTopology(self, options): def registerTopology(self, options):
""" Called from configs/ruby/Ruby.py """Called from configs/ruby/Ruby.py
There is no return value. This should only be called in There is no return value. This should only be called in
SE mode. It is used by some topology objects to populate SE mode. It is used by some topology objects to populate
the faux filesystem with accurate file contents. the faux filesystem with accurate file contents.
No need to implement if not using FilesystemRegister No need to implement if not using FilesystemRegister
functionality. functionality.
""" """
class SimpleTopology(BaseTopology): class SimpleTopology(BaseTopology):
""" Provides methods needed for the topologies included in Ruby before """Provides methods needed for the topologies included in Ruby before
topology changes. topology changes.
These topologies are "simple" in the sense that they only use a flat These topologies are "simple" in the sense that they only use a flat
list of controllers to construct the topology. list of controllers to construct the topology.
""" """
description = "SimpleTopology" description = "SimpleTopology"

View File

@@ -28,10 +28,10 @@ from topologies.BaseTopology import BaseTopology
class Cluster(BaseTopology): class Cluster(BaseTopology):
""" A cluster is a group of nodes which are all one hop from eachother """A cluster is a group of nodes which are all one hop from eachother
Clusters can also contain other clusters Clusters can also contain other clusters
When creating this kind of topology, return a single cluster (usually When creating this kind of topology, return a single cluster (usually
the root cluster) from create_system in configs/ruby/<protocol>.py the root cluster) from create_system in configs/ruby/<protocol>.py
""" """
_num_int_links = 0 _num_int_links = 0
@@ -55,13 +55,13 @@ class Cluster(BaseTopology):
return cls._num_routers - 1 return cls._num_routers - 1
def __init__(self, intBW=0, extBW=0, intLatency=0, extLatency=0): def __init__(self, intBW=0, extBW=0, intLatency=0, extLatency=0):
""" internalBandwidth is bandwidth of all links within the cluster """internalBandwidth is bandwidth of all links within the cluster
externalBandwidth is bandwidth from this cluster to any cluster externalBandwidth is bandwidth from this cluster to any cluster
connecting to it. connecting to it.
internal/externalLatency are similar internal/externalLatency are similar
**** When creating a cluster with sub-clusters, the sub-cluster **** When creating a cluster with sub-clusters, the sub-cluster
external bandwidth overrides the internal bandwidth of the external bandwidth overrides the internal bandwidth of the
super cluster super cluster
""" """
self.nodes = [] self.nodes = []
self.router = None # created in makeTopology self.router = None # created in makeTopology
@@ -74,8 +74,7 @@ class Cluster(BaseTopology):
self.nodes.append(node) self.nodes.append(node)
def makeTopology(self, options, network, IntLink, ExtLink, Router): def makeTopology(self, options, network, IntLink, ExtLink, Router):
""" Recursively make all of the links and routers """Recursively make all of the links and routers"""
"""
# make a router to connect all of the nodes # make a router to connect all of the nodes
self.router = Router(router_id=self.num_routers()) self.router = Router(router_id=self.num_routers())

View File

@@ -41,13 +41,13 @@
import SCons.Node.FS import SCons.Node.FS
fs = SCons.Node.FS.get_default_fs() fs = SCons.Node.FS.get_default_fs()
root = fs.Dir('#') root = fs.Dir("#")
extra_python_nodes = [ extra_python_nodes = [
root.Dir('src').Dir('python').srcnode(), # gem5 includes root.Dir("src").Dir("python").srcnode(), # gem5 includes
root.Dir('ext').Dir('ply').srcnode(), # ply is used by several files root.Dir("ext").Dir("ply").srcnode(), # ply is used by several files
root.Dir('ext').Dir('Kconfiglib').Dir('import').srcnode(), # kconfiglib root.Dir("ext").Dir("Kconfiglib").Dir("import").srcnode(), # kconfiglib
] ]
extra_python_paths = [ node.abspath for node in extra_python_nodes ] extra_python_paths = [node.abspath for node in extra_python_nodes]
__all__ = ['extra_python_paths'] __all__ = ["extra_python_paths"]

View File

@@ -52,34 +52,38 @@ import SCons.Script
termcap = get_termcap() termcap = get_termcap()
def strip_build_path(path, env): def strip_build_path(path, env):
path = str(path) path = str(path)
build_base = 'build/' build_base = "build/"
variant_base = env['BUILDROOT'] + os.path.sep variant_base = env["BUILDROOT"] + os.path.sep
if path.startswith(variant_base): if path.startswith(variant_base):
path = path[len(variant_base):] path = path[len(variant_base) :]
elif path.startswith(build_base): elif path.startswith(build_base):
path = path[len(build_base):] path = path[len(build_base) :]
return path return path
def TempFileSpawn(scons_env): def TempFileSpawn(scons_env):
old_pspawn = scons_env['PSPAWN'] old_pspawn = scons_env["PSPAWN"]
old_spawn = scons_env['SPAWN'] old_spawn = scons_env["SPAWN"]
def wrapper(old, sh, esc, cmd, sh_args, *py_args): def wrapper(old, sh, esc, cmd, sh_args, *py_args):
with tempfile.NamedTemporaryFile() as temp: with tempfile.NamedTemporaryFile() as temp:
temp.write(' '.join(sh_args).encode()) temp.write(" ".join(sh_args).encode())
temp.flush() temp.flush()
sh_args = [sh, esc(temp.name)] sh_args = [sh, esc(temp.name)]
return old(sh, esc, sh, sh_args, *py_args) return old(sh, esc, sh, sh_args, *py_args)
def new_pspawn(sh, esc, cmd, args, sh_env, stdout, stderr): def new_pspawn(sh, esc, cmd, args, sh_env, stdout, stderr):
return wrapper(old_pspawn, sh, esc, cmd, args, sh_env, stdout, stderr) return wrapper(old_pspawn, sh, esc, cmd, args, sh_env, stdout, stderr)
def new_spawn(sh, esc, cmd, args, sh_env): def new_spawn(sh, esc, cmd, args, sh_env):
return wrapper(old_spawn, sh, esc, cmd, args, sh_env) return wrapper(old_spawn, sh, esc, cmd, args, sh_env)
scons_env['PSPAWN'] = new_pspawn scons_env["PSPAWN"] = new_pspawn
scons_env['SPAWN'] = new_spawn scons_env["SPAWN"] = new_spawn
# Generate a string of the form: # Generate a string of the form:
# common/path/prefix/src1, src2 -> tgt1, tgt2 # common/path/prefix/src1, src2 -> tgt1, tgt2
@@ -93,23 +97,32 @@ class Transform(object):
tgts_color = termcap.Yellow + termcap.Bold tgts_color = termcap.Yellow + termcap.Bold
def __init__(self, tool, max_sources=99): def __init__(self, tool, max_sources=99):
self.format = self.tool_color + (" [%8s] " % tool) \ self.format = (
+ self.pfx_color + "%s" \ self.tool_color
+ self.srcs_color + "%s" \ + (" [%8s] " % tool)
+ self.arrow_color + " -> " \ + self.pfx_color
+ self.tgts_color + "%s" \ + "%s"
+ termcap.Normal + self.srcs_color
+ "%s"
+ self.arrow_color
+ " -> "
+ self.tgts_color
+ "%s"
+ termcap.Normal
)
self.max_sources = max_sources self.max_sources = max_sources
def __call__(self, target, source, env, for_signature=None): def __call__(self, target, source, env, for_signature=None):
# truncate source list according to max_sources param # truncate source list according to max_sources param
source = source[0:self.max_sources] source = source[0 : self.max_sources]
def strip(f): def strip(f):
return strip_build_path(str(f), env) return strip_build_path(str(f), env)
if len(source) > 0: if len(source) > 0:
srcs = list(map(strip, source)) srcs = list(map(strip, source))
else: else:
srcs = [''] srcs = [""]
tgts = list(map(strip, target)) tgts = list(map(strip, target))
# surprisingly, os.path.commonprefix is a dumb char-by-char string # surprisingly, os.path.commonprefix is a dumb char-by-char string
# operation that has nothing to do with paths. # operation that has nothing to do with paths.
@@ -137,20 +150,23 @@ class Transform(object):
if sep_idx != -1: if sep_idx != -1:
com_pfx = com_pfx[0:sep_idx] com_pfx = com_pfx[0:sep_idx]
else: else:
com_pfx = '' com_pfx = ""
elif src0_len > com_pfx_len and srcs[0][com_pfx_len] == ".": elif src0_len > com_pfx_len and srcs[0][com_pfx_len] == ".":
# still splitting at file extension: ok # still splitting at file extension: ok
pass pass
else: else:
# probably a fluke; ignore it # probably a fluke; ignore it
com_pfx = '' com_pfx = ""
# recalculate length in case com_pfx was modified # recalculate length in case com_pfx was modified
com_pfx_len = len(com_pfx) com_pfx_len = len(com_pfx)
def fmt(files): def fmt(files):
f = list(map(lambda s: s[com_pfx_len:], files)) f = list(map(lambda s: s[com_pfx_len:], files))
return ', '.join(f) return ", ".join(f)
return self.format % (com_pfx, fmt(srcs), fmt(tgts)) return self.format % (com_pfx, fmt(srcs), fmt(tgts))
# The width warning and error messages should be wrapped at. # The width warning and error messages should be wrapped at.
text_width = None text_width = None
@@ -162,6 +178,7 @@ if not sys.stdout.isatty():
if text_width is None: if text_width is None:
try: try:
import shutil import shutil
text_width = shutil.get_terminal_size().columns text_width = shutil.get_terminal_size().columns
except: except:
pass pass
@@ -170,6 +187,7 @@ if text_width is None:
if text_width is None: if text_width is None:
try: try:
import curses import curses
try: try:
_, text_width = curses.initscr().getmaxyx() _, text_width = curses.initscr().getmaxyx()
finally: finally:
@@ -181,21 +199,22 @@ if text_width is None:
if text_width is None: if text_width is None:
text_width = 80 text_width = 80
def print_message(prefix, color, message, **kwargs): def print_message(prefix, color, message, **kwargs):
prefix_len = len(prefix) prefix_len = len(prefix)
if text_width > prefix_len: if text_width > prefix_len:
wrap_width = text_width - prefix_len wrap_width = text_width - prefix_len
padding = ' ' * prefix_len padding = " " * prefix_len
# First split on newlines. # First split on newlines.
lines = message.split('\n') lines = message.split("\n")
# Then wrap each line to the required width. # Then wrap each line to the required width.
wrapped_lines = [] wrapped_lines = []
for line in lines: for line in lines:
wrapped_lines.extend(textwrap.wrap(line, wrap_width)) wrapped_lines.extend(textwrap.wrap(line, wrap_width))
# Finally add the prefix and padding on extra lines, and glue it all # Finally add the prefix and padding on extra lines, and glue it all
# back together. # back together.
message = prefix + ('\n' + padding).join(wrapped_lines) message = prefix + ("\n" + padding).join(wrapped_lines)
else: else:
# We have very small terminal, indent formatting doesn't help. # We have very small terminal, indent formatting doesn't help.
message = prefix + message message = prefix + message
@@ -205,27 +224,36 @@ def print_message(prefix, color, message, **kwargs):
print(message, **kwargs) print(message, **kwargs)
return message return message
all_warnings = [] all_warnings = []
def summarize_warnings(): def summarize_warnings():
if not all_warnings: if not all_warnings:
return return
print(termcap.Yellow + termcap.Bold + print(
'*** Summary of Warnings ***' + termcap.Yellow
termcap.Normal) + termcap.Bold
+ "*** Summary of Warnings ***"
+ termcap.Normal
)
list(map(print, all_warnings)) list(map(print, all_warnings))
def warning(*args, **kwargs): def warning(*args, **kwargs):
message = ' '.join(args) message = " ".join(args)
printed = print_message('Warning: ', termcap.Yellow, message, **kwargs) printed = print_message("Warning: ", termcap.Yellow, message, **kwargs)
all_warnings.append(printed) all_warnings.append(printed)
def error(*args, **kwargs): def error(*args, **kwargs):
message = ' '.join(args) message = " ".join(args)
print_message('Error: ', termcap.Red, message, **kwargs) print_message("Error: ", termcap.Red, message, **kwargs)
SCons.Script.Exit(1) SCons.Script.Exit(1)
def parse_build_path(target): def parse_build_path(target):
path_dirs = target.split('/') path_dirs = target.split("/")
# Pop off the target file. # Pop off the target file.
path_dirs.pop() path_dirs.pop()
@@ -233,40 +261,55 @@ def parse_build_path(target):
# Search backwards for the "build" directory. Whatever was just before it # Search backwards for the "build" directory. Whatever was just before it
# was the name of the variant. # was the name of the variant.
variant_dir = path_dirs.pop() variant_dir = path_dirs.pop()
while path_dirs and path_dirs[-1] != 'build': while path_dirs and path_dirs[-1] != "build":
variant_dir = path_dirs.pop() variant_dir = path_dirs.pop()
if not path_dirs: if not path_dirs:
error("No non-leaf 'build' dir found on target path.", t) error("No non-leaf 'build' dir found on target path.", t)
return os.path.join('/', *path_dirs), variant_dir return os.path.join("/", *path_dirs), variant_dir
# The MakeAction wrapper, and a SCons tool to set up the *COMSTR variables. # The MakeAction wrapper, and a SCons tool to set up the *COMSTR variables.
if SCons.Script.GetOption('verbose'): if SCons.Script.GetOption("verbose"):
def MakeAction(action, string, *args, **kwargs): def MakeAction(action, string, *args, **kwargs):
return SCons.Script.Action(action, *args, **kwargs) return SCons.Script.Action(action, *args, **kwargs)
def MakeActionTool(env): def MakeActionTool(env):
pass pass
else: else:
MakeAction = SCons.Script.Action MakeAction = SCons.Script.Action
def MakeActionTool(env): def MakeActionTool(env):
env['CCCOMSTR'] = Transform("CC") env["CCCOMSTR"] = Transform("CC")
env['CXXCOMSTR'] = Transform("CXX") env["CXXCOMSTR"] = Transform("CXX")
env['ASCOMSTR'] = Transform("AS") env["ASCOMSTR"] = Transform("AS")
env['ARCOMSTR'] = Transform("AR", 0) env["ARCOMSTR"] = Transform("AR", 0)
env['LINKCOMSTR'] = Transform("LINK", 0) env["LINKCOMSTR"] = Transform("LINK", 0)
env['SHLINKCOMSTR'] = Transform("SHLINK", 0) env["SHLINKCOMSTR"] = Transform("SHLINK", 0)
env['RANLIBCOMSTR'] = Transform("RANLIB", 0) env["RANLIBCOMSTR"] = Transform("RANLIB", 0)
env['M4COMSTR'] = Transform("M4") env["M4COMSTR"] = Transform("M4")
env['SHCCCOMSTR'] = Transform("SHCC") env["SHCCCOMSTR"] = Transform("SHCC")
env['SHCXXCOMSTR'] = Transform("SHCXX") env["SHCXXCOMSTR"] = Transform("SHCXX")
def ToValue(obj): def ToValue(obj):
return SCons.Node.Python.Value(pickle.dumps(obj)) return SCons.Node.Python.Value(pickle.dumps(obj))
def FromValue(node): def FromValue(node):
return pickle.loads(node.read()) return pickle.loads(node.read())
__all__ = ['Configure', 'EnvDefaults', 'Transform', 'warning', 'error',
'MakeAction', 'MakeActionTool', 'ToValue', 'FromValue'] __all__ = [
"Configure",
"EnvDefaults",
"Transform",
"warning",
"error",
"MakeAction",
"MakeActionTool",
"ToValue",
"FromValue",
]

View File

@@ -43,26 +43,23 @@ import sys
import SCons.Node.FS import SCons.Node.FS
def AddLocalRPATH(env): def AddLocalRPATH(env):
def add_local_rpath(env, *targets): def add_local_rpath(env, *targets):
'''Set up an RPATH for a library which lives in the build directory. """Set up an RPATH for a library which lives in the build directory.
The construction environment variable BIN_RPATH_PREFIX should be set The construction environment variable BIN_RPATH_PREFIX should be set
to the relative path of the build directory starting from the location to the relative path of the build directory starting from the location
of the binary.''' of the binary."""
for target in targets: for target in targets:
target = env.Entry(target) target = env.Entry(target)
if not isinstance(target, SCons.Node.FS.Dir): if not isinstance(target, SCons.Node.FS.Dir):
target = target.dir target = target.dir
relpath = os.path.relpath(target.abspath, env['BUILDDIR']) relpath = os.path.relpath(target.abspath, env["BUILDDIR"])
components = [ components = ["\\$$ORIGIN", "${BIN_RPATH_PREFIX}", relpath]
'\\$$ORIGIN',
'${BIN_RPATH_PREFIX}',
relpath
]
env.Append(RPATH=[env.Literal(os.path.join(*components))]) env.Append(RPATH=[env.Literal(os.path.join(*components))])
if sys.platform != "darwin": if sys.platform != "darwin":
env.Append(LINKFLAGS=env.Split('-z origin')) env.Append(LINKFLAGS=env.Split("-z origin"))
env.AddMethod(add_local_rpath, 'AddLocalRPATH') env.AddMethod(add_local_rpath, "AddLocalRPATH")

View File

@@ -46,19 +46,21 @@ from code_formatter import code_formatter
import SCons.Node.Python import SCons.Node.Python
def build_blob(target, source, env): def build_blob(target, source, env):
''' """
Embed an arbitrary blob into the gem5 executable, Embed an arbitrary blob into the gem5 executable,
and make it accessible to C++ as a byte array. and make it accessible to C++ as a byte array.
''' """
with open(str(source[0]), 'rb') as f: with open(str(source[0]), "rb") as f:
data = f.read() data = f.read()
symbol = str(source[1]) symbol = str(source[1])
cc, hh = target cc, hh = target
hh_code = code_formatter() hh_code = code_formatter()
hh_code('''\ hh_code(
"""\
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
@@ -72,13 +74,15 @@ extern const std::uint8_t ${symbol}[];
} // namespace Blobs } // namespace Blobs
} // namespace gem5 } // namespace gem5
''') """
)
hh_code.write(str(hh)) hh_code.write(str(hh))
include_path = os.path.relpath(hh.abspath, env['BUILDDIR']) include_path = os.path.relpath(hh.abspath, env["BUILDDIR"])
cc_code = code_formatter() cc_code = code_formatter()
cc_code('''\ cc_code(
"""\
#include "${include_path}" #include "${include_path}"
namespace gem5 namespace gem5
@@ -87,22 +91,28 @@ namespace Blobs
{ {
const std::size_t ${symbol}_len = ${{len(data)}}; const std::size_t ${symbol}_len = ${{len(data)}};
''') """
)
bytesToCppArray(cc_code, symbol, data) bytesToCppArray(cc_code, symbol, data)
cc_code(''' cc_code(
"""
} // namespace Blobs } // namespace Blobs
} // namespace gem5 } // namespace gem5
''') """
)
cc_code.write(str(cc)) cc_code.write(str(cc))
blob_action = MakeAction(build_blob, Transform("EMBED BLOB")) blob_action = MakeAction(build_blob, Transform("EMBED BLOB"))
def blob_emitter(target, source, env): def blob_emitter(target, source, env):
symbol = str(target[0]) symbol = str(target[0])
cc_file = env.File(symbol + '.cc') cc_file = env.File(symbol + ".cc")
hh_file = env.File(symbol + '.hh') hh_file = env.File(symbol + ".hh")
return [cc_file, hh_file], [source, SCons.Node.Python.Value(symbol)] return [cc_file, hh_file], [source, SCons.Node.Python.Value(symbol)]
def Blob(env): def Blob(env):
blob_builder = env.Builder(action=blob_action, emitter=blob_emitter) blob_builder = env.Builder(action=blob_action, emitter=blob_emitter)
env.Append(BUILDERS={'Blob': blob_builder}) env.Append(BUILDERS={"Blob": blob_builder})

View File

@@ -46,15 +46,16 @@ from gem5_scons import Transform, MakeAction
# #
################################################### ###################################################
def ConfigFile(env): def ConfigFile(env):
# This function generates a config header file that #defines the # This function generates a config header file that #defines the
# variable symbol to the current variable setting (0 or 1). The source # variable symbol to the current variable setting (0 or 1). The source
# operands are the name of the variable and a Value node containing the # operands are the name of the variable and a Value node containing the
# value of the variable. # value of the variable.
def build_config_file(target, source, env): def build_config_file(target, source, env):
(variable, value) = [s.get_contents().decode('utf-8') for s in source] (variable, value) = [s.get_contents().decode("utf-8") for s in source]
with open(str(target[0].abspath), 'w') as f: with open(str(target[0].abspath), "w") as f:
print('#define', variable, value, file=f) print("#define", variable, value, file=f)
return None return None
# Combine the two functions into a scons Action object. # Combine the two functions into a scons Action object.
@@ -66,8 +67,8 @@ def ConfigFile(env):
# extract variable name from Builder arg # extract variable name from Builder arg
variable = str(target[0]) variable = str(target[0])
# True target is config header file # True target is config header file
target = env.Dir('config').File(variable.lower() + '.hh') target = env.Dir("config").File(variable.lower() + ".hh")
val = env['CONF'][variable] val = env["CONF"][variable]
if isinstance(val, bool): if isinstance(val, bool):
# Force value to 0/1 # Force value to 0/1
val = str(int(val)) val = str(int(val))
@@ -79,4 +80,4 @@ def ConfigFile(env):
config_builder = env.Builder(emitter=config_emitter, action=config_action) config_builder = env.Builder(emitter=config_emitter, action=config_action)
env.Append(BUILDERS = { 'ConfigFile' : config_builder }) env.Append(BUILDERS={"ConfigFile": config_builder})

View File

@@ -51,27 +51,32 @@ from gem5_scons import Transform, MakeAction
# #
################################################### ###################################################
def SwitchingHeaders(env): def SwitchingHeaders(env):
def build_switching_header(target, source, env): def build_switching_header(target, source, env):
path = str(target[0]) path = str(target[0])
subdir = str(source[0]) subdir = str(source[0])
dp, fp = os.path.split(path) dp, fp = os.path.split(path)
dp = os.path.relpath(os.path.realpath(dp), dp = os.path.relpath(
os.path.realpath(env['BUILDDIR'])) os.path.realpath(dp), os.path.realpath(env["BUILDDIR"])
with open(path, 'w') as hdr: )
with open(path, "w") as hdr:
print('#include "%s/%s/%s"' % (dp, subdir, fp), file=hdr) print('#include "%s/%s/%s"' % (dp, subdir, fp), file=hdr)
switching_header_action = MakeAction(build_switching_header, switching_header_action = MakeAction(
Transform('GENERATE')) build_switching_header, Transform("GENERATE")
)
switching_header_builder = env.Builder(action=switching_header_action, switching_header_builder = env.Builder(
source_factory=env.Value, action=switching_header_action,
single_source=True) source_factory=env.Value,
single_source=True,
)
env.Append(BUILDERS = { 'SwitchingHeader': switching_header_builder }) env.Append(BUILDERS={"SwitchingHeader": switching_header_builder})
def switching_headers(self, headers, source): def switching_headers(self, headers, source):
for header in headers: for header in headers:
self.SwitchingHeader(header, source) self.SwitchingHeader(header, source)
env.AddMethod(switching_headers, 'SwitchingHeaders') env.AddMethod(switching_headers, "SwitchingHeaders")

View File

@@ -44,39 +44,41 @@ import os
import SCons.Script import SCons.Script
import SCons.Util import SCons.Util
def CheckCxxFlag(context, flag, autoadd=True): def CheckCxxFlag(context, flag, autoadd=True):
context.Message("Checking for compiler %s support... " % flag) context.Message("Checking for compiler %s support... " % flag)
last_cxxflags = context.env['CXXFLAGS'] last_cxxflags = context.env["CXXFLAGS"]
context.env.Append(CXXFLAGS=[flag]) context.env.Append(CXXFLAGS=[flag])
pre_werror = context.env['CXXFLAGS'] pre_werror = context.env["CXXFLAGS"]
context.env.Append(CXXFLAGS=['-Werror']) context.env.Append(CXXFLAGS=["-Werror"])
ret = context.TryCompile('// CheckCxxFlag DO NOTHING', '.cc') ret = context.TryCompile("// CheckCxxFlag DO NOTHING", ".cc")
context.env['CXXFLAGS'] = pre_werror context.env["CXXFLAGS"] = pre_werror
if not (ret and autoadd): if not (ret and autoadd):
context.env['CXXFLAGS'] = last_cxxflags context.env["CXXFLAGS"] = last_cxxflags
context.Result(ret) context.Result(ret)
return ret return ret
def CheckLinkFlag(context, flag, autoadd=True, set_for_shared=True): def CheckLinkFlag(context, flag, autoadd=True, set_for_shared=True):
context.Message("Checking for linker %s support... " % flag) context.Message("Checking for linker %s support... " % flag)
last_linkflags = context.env['LINKFLAGS'] last_linkflags = context.env["LINKFLAGS"]
context.env.Append(LINKFLAGS=[flag]) context.env.Append(LINKFLAGS=[flag])
pre_werror = context.env['LINKFLAGS'] pre_werror = context.env["LINKFLAGS"]
context.env.Append(LINKFLAGS=['-Werror']) context.env.Append(LINKFLAGS=["-Werror"])
ret = context.TryLink('int main(int, char *[]) { return 0; }', '.cc') ret = context.TryLink("int main(int, char *[]) { return 0; }", ".cc")
context.env['LINKFLAGS'] = pre_werror context.env["LINKFLAGS"] = pre_werror
if not (ret and autoadd): if not (ret and autoadd):
context.env['LINKFLAGS'] = last_linkflags context.env["LINKFLAGS"] = last_linkflags
if (ret and set_for_shared): if ret and set_for_shared:
assert(autoadd) assert autoadd
context.env.Append(SHLINKFLAGS=[flag]) context.env.Append(SHLINKFLAGS=[flag])
context.Result(ret) context.Result(ret)
return ret return ret
# Add a custom Check function to test for structure members. # Add a custom Check function to test for structure members.
def CheckMember(context, include, decl, member, include_quotes="<>"): def CheckMember(context, include, decl, member, include_quotes="<>"):
context.Message("Checking for member %s in %s..." % context.Message("Checking for member %s in %s..." % (member, decl))
(member, decl))
text = """ text = """
#include %(header)s #include %(header)s
int main(){ int main(){
@@ -84,18 +86,21 @@ int main(){
(void)test.%(member)s; (void)test.%(member)s;
return 0; return 0;
}; };
""" % { "header" : include_quotes[0] + include + include_quotes[1], """ % {
"decl" : decl, "header": include_quotes[0] + include + include_quotes[1],
"member" : member, "decl": decl,
} "member": member,
}
ret = context.TryCompile(text, extension=".cc") ret = context.TryCompile(text, extension=".cc")
context.Result(ret) context.Result(ret)
return ret return ret
def CheckPythonLib(context): def CheckPythonLib(context):
context.Message('Checking Python version... ') context.Message("Checking Python version... ")
ret = context.TryRun(r""" ret = context.TryRun(
r"""
#include <pybind11/embed.h> #include <pybind11/embed.h>
int int
@@ -107,21 +112,24 @@ main(int argc, char **argv) {
"sys.stdout.write('%i.%i.%i' % (vi.major, vi.minor, vi.micro));\n"); "sys.stdout.write('%i.%i.%i' % (vi.major, vi.minor, vi.micro));\n");
return 0; return 0;
} }
""", extension=".cc") """,
extension=".cc",
)
context.Result(ret[1] if ret[0] == 1 else 0) context.Result(ret[1] if ret[0] == 1 else 0)
if ret[0] == 0: if ret[0] == 0:
return None return None
else: else:
return tuple(map(int, ret[1].split("."))) return tuple(map(int, ret[1].split(".")))
def CheckPkgConfig(context, pkgs, *args): def CheckPkgConfig(context, pkgs, *args):
if not SCons.Util.is_List(pkgs): if not SCons.Util.is_List(pkgs):
pkgs = [pkgs] pkgs = [pkgs]
assert(pkgs) assert pkgs
for pkg in pkgs: for pkg in pkgs:
context.Message('Checking for pkg-config package %s... ' % pkg) context.Message("Checking for pkg-config package %s... " % pkg)
ret = context.TryAction('pkg-config %s' % pkg)[0] ret = context.TryAction("pkg-config %s" % pkg)[0]
if not ret: if not ret:
context.Result(ret) context.Result(ret)
continue continue
@@ -129,7 +137,7 @@ def CheckPkgConfig(context, pkgs, *args):
if len(args) == 0: if len(args) == 0:
break break
cmd = ' '.join(['pkg-config'] + list(args) + [pkg]) cmd = " ".join(["pkg-config"] + list(args) + [pkg])
try: try:
context.env.ParseConfig(cmd) context.env.ParseConfig(cmd)
ret = 1 ret = 1
@@ -141,20 +149,25 @@ def CheckPkgConfig(context, pkgs, *args):
return ret return ret
@contextlib.contextmanager @contextlib.contextmanager
def Configure(env, *args, **kwargs): def Configure(env, *args, **kwargs):
kwargs.setdefault('conf_dir', kwargs.setdefault(
os.path.join(env['GEM5BUILD'], 'scons_config')) "conf_dir", os.path.join(env["GEM5BUILD"], "scons_config")
kwargs.setdefault('log_file', )
os.path.join(env['GEM5BUILD'], 'scons_config.log')) kwargs.setdefault(
kwargs.setdefault('custom_tests', {}) "log_file", os.path.join(env["GEM5BUILD"], "scons_config.log")
kwargs['custom_tests'].update({ )
'CheckCxxFlag' : CheckCxxFlag, kwargs.setdefault("custom_tests", {})
'CheckLinkFlag' : CheckLinkFlag, kwargs["custom_tests"].update(
'CheckMember' : CheckMember, {
'CheckPkgConfig' : CheckPkgConfig, "CheckCxxFlag": CheckCxxFlag,
'CheckPythonLib' : CheckPythonLib, "CheckLinkFlag": CheckLinkFlag,
}) "CheckMember": CheckMember,
"CheckPkgConfig": CheckPkgConfig,
"CheckPythonLib": CheckPythonLib,
}
)
conf = SCons.Script.Configure(env, *args, **kwargs) conf = SCons.Script.Configure(env, *args, **kwargs)
# Recent versions of scons substitute a "Null" object for Configure() # Recent versions of scons substitute a "Null" object for Configure()
@@ -163,14 +176,17 @@ def Configure(env, *args, **kwargs):
# breaking all our configuration checks. We replace it with our own # breaking all our configuration checks. We replace it with our own
# more optimistic null object that returns True instead. # more optimistic null object that returns True instead.
if not conf: if not conf:
def NullCheck(*args, **kwargs): def NullCheck(*args, **kwargs):
return True return True
class NullConf: class NullConf:
def __init__(self, env): def __init__(self, env):
self.env = env self.env = env
def Finish(self): def Finish(self):
return self.env return self.env
def __getattr__(self, mname): def __getattr__(self, mname):
return NullCheck return NullCheck

View File

@@ -42,56 +42,76 @@ import os
from gem5_python_paths import extra_python_paths from gem5_python_paths import extra_python_paths
def EnvDefaults(env): def EnvDefaults(env):
# export TERM so that clang reports errors in color # export TERM so that clang reports errors in color
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', use_vars = set(
'LIBRARY_PATH', 'PATH', 'PKG_CONFIG_PATH', 'PROTOC', [
'PYTHONPATH', 'RANLIB', 'TERM', 'PYTHON_CONFIG', "AS",
'CCFLAGS_EXTRA', 'GEM5PY_CCFLAGS_EXTRA', "AR",
'GEM5PY_LINKFLAGS_EXTRA', 'LINKFLAGS_EXTRA', 'LANG']) "CC",
"CXX",
"HOME",
"LD_LIBRARY_PATH",
"LIBRARY_PATH",
"PATH",
"PKG_CONFIG_PATH",
"PROTOC",
"PYTHONPATH",
"RANLIB",
"TERM",
"PYTHON_CONFIG",
"CCFLAGS_EXTRA",
"GEM5PY_CCFLAGS_EXTRA",
"GEM5PY_LINKFLAGS_EXTRA",
"LINKFLAGS_EXTRA",
"LANG",
]
)
use_prefixes = [ use_prefixes = [
"ASAN_", # address sanitizer symbolizer path and settings "ASAN_", # address sanitizer symbolizer path and settings
"CCACHE_", # ccache (caching compiler wrapper) configuration "CCACHE_", # ccache (caching compiler wrapper) configuration
"CCC_", # clang static analyzer configuration "CCC_", # clang static analyzer configuration
"DISTCC_", # distcc (distributed compiler wrapper) config "DISTCC_", # distcc (distributed compiler wrapper) config
"INCLUDE_SERVER_", # distcc pump server settings "INCLUDE_SERVER_", # distcc pump server settings
"M5", # M5 configuration (e.g., path to kernels) "M5", # M5 configuration (e.g., path to kernels)
"NIX_", # wrapped binaries if using nix package manager "NIX_", # wrapped binaries if using nix package manager
] ]
for key,val in sorted(os.environ.items()): for key, val in sorted(os.environ.items()):
if key in use_vars or \ if key in use_vars or any(
any([key.startswith(prefix) for prefix in use_prefixes]): [key.startswith(prefix) for prefix in use_prefixes]
env['ENV'][key] = val ):
env["ENV"][key] = val
# These variables from the environment override/become SCons variables, # These variables from the environment override/become SCons variables,
# with a default if they weren't in the host environment. # with a default if they weren't in the host environment.
var_overrides = { var_overrides = {
'CC': env['CC'], "CC": env["CC"],
'CXX': env['CXX'], "CXX": env["CXX"],
'PROTOC': 'protoc', "PROTOC": "protoc",
'PYTHON_CONFIG': [ 'python3-config', 'python-config' ], "PYTHON_CONFIG": ["python3-config", "python-config"],
'CCFLAGS_EXTRA': '', "CCFLAGS_EXTRA": "",
'GEM5PY_CCFLAGS_EXTRA': '', "GEM5PY_CCFLAGS_EXTRA": "",
'GEM5PY_LINKFLAGS_EXTRA': '', "GEM5PY_LINKFLAGS_EXTRA": "",
'LINKFLAGS_EXTRA': '', "LINKFLAGS_EXTRA": "",
} }
for key,default in var_overrides.items(): for key, default in var_overrides.items():
env[key] = env['ENV'].get(key, default) env[key] = env["ENV"].get(key, default)
# Tell scons to avoid implicit command dependencies to avoid issues # Tell scons to avoid implicit command dependencies to avoid issues
# with the param wrappes being compiled twice (see # with the param wrappes being compiled twice (see
# https://github.com/SCons/scons/issues/2811 # https://github.com/SCons/scons/issues/2811
env['IMPLICIT_COMMAND_DEPENDENCIES'] = 0 env["IMPLICIT_COMMAND_DEPENDENCIES"] = 0
env.Decider('MD5-timestamp') env.Decider("MD5-timestamp")
# add useful python code PYTHONPATH so it can be used by subprocesses # add useful python code PYTHONPATH so it can be used by subprocesses
# as well # as well
env.AppendENVPath('PYTHONPATH', extra_python_paths) env.AppendENVPath("PYTHONPATH", extra_python_paths)
# Default duplicate option is to use hard links, but this messes up # Default duplicate option is to use hard links, but this messes up
# when you use emacs to edit a file in the target dir, as emacs moves # when you use emacs to edit a file in the target dir, as emacs moves
# file to file~ then copies to file, breaking the link. Symbolic # file to file~ then copies to file, breaking the link. Symbolic
# (soft) links work better. # (soft) links work better.
env.SetOption('duplicate', 'soft-copy') env.SetOption("duplicate", "soft-copy")

View File

@@ -47,8 +47,9 @@ import SCons.Script
# When specifying a source file of some type, a set of tags can be # When specifying a source file of some type, a set of tags can be
# specified for that file. # specified for that file.
def tag_implies(env, tag, tag_list): def tag_implies(env, tag, tag_list):
''' """
Associates a tag X to a list of tags which are implied by X. Associates a tag X to a list of tags which are implied by X.
For example, assume: For example, assume:
@@ -72,10 +73,10 @@ def tag_implies(env, tag, tag_list):
So that any use of a tag will automatically include its transitive tags So that any use of a tag will automatically include its transitive tags
after being resolved. after being resolved.
''' """
env.SetDefault(_tag_implies={}) env.SetDefault(_tag_implies={})
implications = env['_tag_implies'] implications = env["_tag_implies"]
if isinstance(tag_list, str): if isinstance(tag_list, str):
tag_list = frozenset([tag_list]) tag_list = frozenset([tag_list])
@@ -95,21 +96,23 @@ def tag_implies(env, tag, tag_list):
# Check if another tag depends on this tag. If so, add this tag's # Check if another tag depends on this tag. If so, add this tag's
# implications to that tag. # implications to that tag.
for t,implied in implications.items(): for t, implied in implications.items():
if tag in implied: if tag in implied:
implications[t] |= implications[tag] implications[t] |= implications[tag]
def TagImpliesTool(env): def TagImpliesTool(env):
env.AddMethod(tag_implies, 'TagImplies') env.AddMethod(tag_implies, "TagImplies")
def resolve_tags(env, tags): def resolve_tags(env, tags):
''' """
Returns the complete set of tags implied (dependencies) by the Returns the complete set of tags implied (dependencies) by the
supplied tags. supplied tags.
''' """
implications = env.SetDefault(_tag_implies={}) implications = env.SetDefault(_tag_implies={})
implications = env['_tag_implies'] implications = env["_tag_implies"]
if isinstance(tags, str): if isinstance(tags, str):
tags = frozenset([tags]) tags = frozenset([tags])
@@ -122,53 +125,71 @@ def resolve_tags(env, tags):
tags |= implications[tag] tags |= implications[tag]
return tags return tags
class SourceFilter(object): class SourceFilter(object):
factories = {} factories = {}
def __init__(self, predicate): def __init__(self, predicate):
self.predicate = predicate self.predicate = predicate
def __or__(self, other): def __or__(self, other):
return SourceFilter(lambda env, tags: self.predicate(env, tags) or return SourceFilter(
other.predicate(env, tags)) lambda env, tags: self.predicate(env, tags)
or other.predicate(env, tags)
)
def __and__(self, other): def __and__(self, other):
return SourceFilter(lambda env, tags: self.predicate(env, tags) and return SourceFilter(
other.predicate(env, tags)) lambda env, tags: self.predicate(env, tags)
and other.predicate(env, tags)
)
def with_any_tags(*tags): def with_any_tags(*tags):
'''Return a list of sources with any of the supplied tags.''' """Return a list of sources with any of the supplied tags."""
return SourceFilter(lambda env, stags: \ return SourceFilter(
len(resolve_tags(env, tags) & stags) > 0) lambda env, stags: len(resolve_tags(env, tags) & stags) > 0
)
def with_all_tags(*tags): def with_all_tags(*tags):
'''Return a list of sources with all of the supplied tags.''' """Return a list of sources with all of the supplied tags."""
return SourceFilter(lambda env, stags: resolve_tags(env, tags) <= stags) return SourceFilter(lambda env, stags: resolve_tags(env, tags) <= stags)
def with_tag(tag): def with_tag(tag):
'''Return a list of sources with the supplied tag.''' """Return a list of sources with the supplied tag."""
return with_any_tags(*[tag]) return with_any_tags(*[tag])
def without_tags(*tags): def without_tags(*tags):
'''Return a list of sources without any of the supplied tags.''' """Return a list of sources without any of the supplied tags."""
return SourceFilter(lambda env, stags: \ return SourceFilter(
len(resolve_tags(env, tags) & stags) == 0) lambda env, stags: len(resolve_tags(env, tags) & stags) == 0
)
def without_tag(tag): def without_tag(tag):
'''Return a list of sources without the supplied tag.''' """Return a list of sources without the supplied tag."""
return without_tags(*[tag]) return without_tags(*[tag])
SourceFilter.factories.update({
'with_any_tags': with_any_tags, SourceFilter.factories.update(
'with_all_tags': with_all_tags, {
'with_tag': with_tag, "with_any_tags": with_any_tags,
'without_tags': without_tags, "with_all_tags": with_all_tags,
'without_tag': without_tag, "with_tag": with_tag,
}) "without_tags": without_tags,
"without_tag": without_tag,
}
)
class SourceList(list): class SourceList(list):
def apply_filter(self, env, f): def apply_filter(self, env, f):
def match(source): def match(source):
return f.predicate(env, resolve_tags(env, source.tags)) return f.predicate(env, resolve_tags(env, source.tags))
return SourceList(filter(match, self)) return SourceList(filter(match, self))
def __getattr__(self, name): def __getattr__(self, name):
@@ -179,33 +200,38 @@ class SourceList(list):
@functools.wraps(func) @functools.wraps(func)
def wrapper(env, *args, **kwargs): def wrapper(env, *args, **kwargs):
return self.apply_filter(env, func(*args, **kwargs)) return self.apply_filter(env, func(*args, **kwargs))
return wrapper return wrapper
class SourceMeta(type): class SourceMeta(type):
'''Meta class for source files that keeps track of all files of a """Meta class for source files that keeps track of all files of a
particular type.''' particular type."""
def __init__(cls, name, bases, dict): def __init__(cls, name, bases, dict):
super(SourceMeta, cls).__init__(name, bases, dict) super(SourceMeta, cls).__init__(name, bases, dict)
cls.all = SourceList() cls.all = SourceList()
class SourceItem(object, metaclass=SourceMeta): class SourceItem(object, metaclass=SourceMeta):
'''Base object that encapsulates the notion of a source component for """Base object that encapsulates the notion of a source component for
gem5. This specifies a set of tags which help group components into groups gem5. This specifies a set of tags which help group components into groups
based on arbitrary properties.''' based on arbitrary properties."""
def __init__(self, source, tags=None, add_tags=None, append=None): def __init__(self, source, tags=None, add_tags=None, append=None):
self.source = source self.source = source
if tags is None: if tags is None:
tags='gem5 lib' tags = "gem5 lib"
if isinstance(tags, str): if isinstance(tags, str):
tags = { tags } tags = {tags}
if not isinstance(tags, set): if not isinstance(tags, set):
tags = set(tags) tags = set(tags)
self.tags = tags.copy() self.tags = tags.copy()
if add_tags: if add_tags:
if isinstance(add_tags, str): if isinstance(add_tags, str):
add_tags = { add_tags } add_tags = {add_tags}
if not isinstance(add_tags, set): if not isinstance(add_tags, set):
add_tags = set(add_tags) add_tags = set(add_tags)
self.tags |= add_tags self.tags |= add_tags
@@ -216,10 +242,11 @@ class SourceItem(object, metaclass=SourceMeta):
if issubclass(base, SourceItem): if issubclass(base, SourceItem):
base.all.append(self) base.all.append(self)
class SourceFile(SourceItem): class SourceFile(SourceItem):
'''Base object that encapsulates the notion of a source file. """Base object that encapsulates the notion of a source file.
This includes, the source node, target node, various manipulations This includes, the source node, target node, various manipulations
of those.''' of those."""
def __init__(self, source, tags=None, add_tags=None, append=None): def __init__(self, source, tags=None, add_tags=None, append=None):
super().__init__(source, tags=tags, add_tags=add_tags, append=append) super().__init__(source, tags=tags, add_tags=add_tags, append=append)
@@ -243,6 +270,15 @@ class SourceFile(SourceItem):
return env.SharedObject(self.tnode) return env.SharedObject(self.tnode)
__all__ = ['TagImpliesTool', 'SourceFilter', 'SourceList', 'SourceFile', __all__ = [
'SourceItem', 'with_any_tags', 'with_all_tags', 'with_tag', "TagImpliesTool",
'without_tags', 'without_tag'] "SourceFilter",
"SourceList",
"SourceFile",
"SourceItem",
"with_any_tags",
"with_all_tags",
"with_tag",
"without_tags",
"without_tag",
]

View File

@@ -46,12 +46,15 @@ import SCons.Script
import m5.util.terminal import m5.util.terminal
def ignore_style(): def ignore_style():
"""Determine whether we should ignore style checks""" """Determine whether we should ignore style checks"""
return SCons.Script.GetOption('ignore_style') or not sys.stdin.isatty() return SCons.Script.GetOption("ignore_style") or not sys.stdin.isatty()
def get_termcap(): def get_termcap():
return m5.util.terminal.get_termcap(SCons.Script.GetOption('use_colors')) return m5.util.terminal.get_termcap(SCons.Script.GetOption("use_colors"))
def readCommand(cmd, **kwargs): def readCommand(cmd, **kwargs):
""" """
@@ -68,13 +71,13 @@ def readCommand(cmd, **kwargs):
if isinstance(cmd, str): if isinstance(cmd, str):
cmd = cmd.split() cmd = cmd.split()
no_exception = 'exception' in kwargs no_exception = "exception" in kwargs
exception = kwargs.pop('exception', None) exception = kwargs.pop("exception", None)
kwargs.setdefault('shell', False) kwargs.setdefault("shell", False)
kwargs.setdefault('stdout', PIPE) kwargs.setdefault("stdout", PIPE)
kwargs.setdefault('stderr', STDOUT) kwargs.setdefault("stderr", STDOUT)
kwargs.setdefault('close_fds', True) kwargs.setdefault("close_fds", True)
try: try:
subp = Popen(cmd, **kwargs) subp = Popen(cmd, **kwargs)
except Exception as e: except Exception as e:
@@ -82,20 +85,23 @@ def readCommand(cmd, **kwargs):
return -1, exception return -1, exception
raise raise
output = subp.communicate()[0].decode('utf-8') output = subp.communicate()[0].decode("utf-8")
return output return output
def compareVersions(v1, v2): def compareVersions(v1, v2):
"""helper function: compare arrays or strings of version numbers. """helper function: compare arrays or strings of version numbers.
E.g., compare_version((1,3,25), (1,4,1)') E.g., compare_version((1,3,25), (1,4,1)')
returns -1, 0, 1 if v1 is <, ==, > v2 returns -1, 0, 1 if v1 is <, ==, > v2
""" """
def make_version_list(v): def make_version_list(v):
if isinstance(v, (list,tuple)): if isinstance(v, (list, tuple)):
return v return v
elif isinstance(v, str): elif isinstance(v, str):
return list(map(lambda x: int(re.match('\d+', x).group()), return list(
v.split('.'))) map(lambda x: int(re.match("\d+", x).group()), v.split("."))
)
else: else:
raise TypeError() raise TypeError()
@@ -104,8 +110,10 @@ def compareVersions(v1, v2):
# Compare corresponding elements of lists # Compare corresponding elements of lists
# The shorter list is filled with 0 till the lists have the same length # The shorter list is filled with 0 till the lists have the same length
for n1,n2 in itertools.zip_longest(v1, v2, fillvalue=0): for n1, n2 in itertools.zip_longest(v1, v2, fillvalue=0):
if n1 < n2: return -1 if n1 < n2:
if n1 > n2: return 1 return -1
if n1 > n2:
return 1
return 0 return 0

View File

@@ -44,10 +44,12 @@ from __future__ import print_function
try: try:
EnsureSConsVersion(3, 0, 0) EnsureSConsVersion(3, 0, 0)
except SystemExit as e: except SystemExit as e:
print(""" print(
"""
For more details, see: For more details, see:
http://gem5.org/documentation/general_docs/building http://gem5.org/documentation/general_docs/building
""") """
)
raise raise
@@ -55,7 +57,8 @@ For more details, see:
try: try:
EnsurePythonVersion(3, 6) EnsurePythonVersion(3, 6)
except SystemExit as e: except SystemExit as e:
print("""\033[93m print(
"""\033[93m
Python 3 is now required. Python 3 is now required.
The following are steps to compile gem5 in Python 3 environment, The following are steps to compile gem5 in Python 3 environment,
@@ -81,7 +84,8 @@ Python 3 environment,
(Optional) For convenience reasons, you can set up an alias for the Python3 \ (Optional) For convenience reasons, you can set up an alias for the Python3 \
scons phrase in your environment. \033[0m scons phrase in your environment. \033[0m
""") """
)
raise raise
from gem5_python_paths import extra_python_paths from gem5_python_paths import extra_python_paths

View File

@@ -50,15 +50,20 @@ to ensure that your code follows gem5's style rules on git commit.
This script will now install the hook in your .git/hooks/ directory. This script will now install the hook in your .git/hooks/ directory.
Press enter to continue, or ctrl-c to abort: """ Press enter to continue, or ctrl-c to abort: """
def install_style_hooks(env): def install_style_hooks(env):
try: try:
gitdir = env.Dir(gem5_scons.util.readCommand( gitdir = env.Dir(
["git", "rev-parse", "--git-dir"]).strip("\n")) gem5_scons.util.readCommand(
["git", "rev-parse", "--git-dir"]
).strip("\n")
)
except Exception as e: except Exception as e:
print("Warning: Failed to find git repo directory: %s" % e) print("Warning: Failed to find git repo directory: %s" % e)
return return
git_hooks = gitdir.Dir("hooks") git_hooks = gitdir.Dir("hooks")
def hook_exists(hook_name): def hook_exists(hook_name):
hook = git_hooks.File(hook_name) hook = git_hooks.File(hook_name)
return hook.exists() return hook.exists()
@@ -66,8 +71,9 @@ def install_style_hooks(env):
def hook_install(hook_name, script): def hook_install(hook_name, script):
hook = git_hooks.File(hook_name) hook = git_hooks.File(hook_name)
if hook.exists(): if hook.exists():
print("Warning: Can't install %s, hook already exists." % print(
hook_name) "Warning: Can't install %s, hook already exists." % hook_name
)
return return
if hook.islink(): if hook.islink():
@@ -78,15 +84,17 @@ def install_style_hooks(env):
os.mkdir(git_hooks.get_abspath()) os.mkdir(git_hooks.get_abspath())
git_hooks.clear() git_hooks.clear()
abs_symlink_hooks = git_hooks.islink() and \ abs_symlink_hooks = git_hooks.islink() and os.path.isabs(
os.path.isabs(os.readlink(git_hooks.get_abspath())) os.readlink(git_hooks.get_abspath())
)
# Use a relative symlink if the hooks live in the source directory, # Use a relative symlink if the hooks live in the source directory,
# and the hooks directory is not a symlink to an absolute path. # and the hooks directory is not a symlink to an absolute path.
if hook.is_under(env.Dir("#")) and not abs_symlink_hooks: if hook.is_under(env.Dir("#")) and not abs_symlink_hooks:
script_path = os.path.relpath( script_path = os.path.relpath(
os.path.realpath(script.get_abspath()), os.path.realpath(script.get_abspath()),
os.path.realpath(hook.Dir(".").get_abspath())) os.path.realpath(hook.Dir(".").get_abspath()),
)
else: else:
script_path = script.get_abspath() script_path = script.get_abspath()
@@ -99,8 +107,8 @@ def install_style_hooks(env):
if hook_exists("pre-commit") and hook_exists("commit-msg"): if hook_exists("pre-commit") and hook_exists("commit-msg"):
return return
print(git_style_message, end=' ') print(git_style_message, end=" ")
if SCons.Script.GetOption('install_hooks'): if SCons.Script.GetOption("install_hooks"):
print("Installing revision control hooks automatically.") print("Installing revision control hooks automatically.")
else: else:
try: try:
@@ -115,9 +123,11 @@ def install_style_hooks(env):
hook_install("pre-commit", git_style_script) hook_install("pre-commit", git_style_script)
hook_install("commit-msg", git_msg_script) hook_install("commit-msg", git_msg_script)
def generate(env): def generate(env):
if exists(env) and not gem5_scons.util.ignore_style(): if exists(env) and not gem5_scons.util.ignore_style():
install_style_hooks(env) install_style_hooks(env)
def exists(env): def exists(env):
return env.Entry('#.git').exists() return env.Entry("#.git").exists()

View File

@@ -865,7 +865,7 @@ class FastModelGIC(BaseGic):
return [int(r.split("=")[1], 16) for r in redists] return [int(r.split("=")[1], 16) for r in redists]
def get_addr_ranges(self): def get_addr_ranges(self):
""" Return address ranges that should be served by this GIC """ """Return address ranges that should be served by this GIC"""
sc_gic = self.sc_gic sc_gic = self.sc_gic
gic_frame_size = 0x10000 gic_frame_size = 0x10000
# Add range of distributor # Add range of distributor

View File

@@ -31,9 +31,9 @@ import _m5.arm_fast_model
def set_armlmd_license_file(force=False): def set_armlmd_license_file(force=False):
"""Set the ARMLMD_LICENSE_FILE environment variable. If "force" is """Set the ARMLMD_LICENSE_FILE environment variable. If "force" is
False, then it will only be set if it wasn't already set in the False, then it will only be set if it wasn't already set in the
environment. The value it's set to is the one gem5 was built with. environment. The value it's set to is the one gem5 was built with.
""" """
key = "ARMLMD_LICENSE_FILE" key = "ARMLMD_LICENSE_FILE"
license_file = buildEnv[key] license_file = buildEnv[key]
if force or key not in os.environ: if force or key not in os.environ:

View File

@@ -35,4 +35,3 @@
// ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN // ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
// IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH // IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGES. // DAMAGES.

View File

@@ -43,4 +43,3 @@
Aarch64::aarch64(); Aarch64::aarch64();

View File

@@ -132,4 +132,3 @@ format DataOp {
} }
} }
} }

View File

@@ -56,4 +56,3 @@ def format ArmBkptHlt() {{
} }
''' '''
}}; }};

View File

@@ -1154,4 +1154,3 @@ def format Thumb16MemLit() {{
} }
''' % loadImmClassName(False, True, False) ''' % loadImmClassName(False, True, False)
}}; }};

View File

@@ -202,4 +202,3 @@ def format PredImmOp(code, *opt_flags) {{
decode_block = BasicDecode.subst(iop) decode_block = BasicDecode.subst(iop)
exec_output = PredOpExecute.subst(iop) exec_output = PredOpExecute.subst(iop)
}}; }};

View File

@@ -167,4 +167,3 @@ let {{
cryptoRegRegRegInst("sha256su1", "SHA256SU164", "SimdShaSigma3Op", cryptoRegRegRegInst("sha256su1", "SHA256SU164", "SimdShaSigma3Op",
sha2_enabled, sha256_su1Code) sha2_enabled, sha256_su1Code)
}}; }};

View File

@@ -229,4 +229,3 @@ let {{
raise Exception("Illegal combination of post and writeback") raise Exception("Illegal combination of post and writeback")
return base return base
}}; }};

View File

@@ -186,5 +186,3 @@ def template BranchTarget {{
return std::unique_ptr<PCStateBase>{pc_ptr}; return std::unique_ptr<PCStateBase>{pc_ptr};
} }
}}; }};

View File

@@ -1288,4 +1288,3 @@ def template LoadImmConstructor {{
#endif #endif
} }
}}; }};

View File

@@ -112,12 +112,11 @@ class Template(object):
operands = SubOperandList(self.parser, compositeCode, d.operands) operands = SubOperandList(self.parser, compositeCode, d.operands)
myDict["reg_idx_arr_decl"] = ( myDict[
"RegId srcRegIdxArr[%d]; RegId destRegIdxArr[%d]" "reg_idx_arr_decl"
% ( ] = "RegId srcRegIdxArr[%d]; RegId destRegIdxArr[%d]" % (
d.operands.numSrcRegs + d.srcRegIdxPadding, d.operands.numSrcRegs + d.srcRegIdxPadding,
d.operands.numDestRegs + d.destRegIdxPadding, d.operands.numDestRegs + d.destRegIdxPadding,
)
) )
# The reinterpret casts are largely because an array with a known # The reinterpret casts are largely because an array with a known
@@ -960,15 +959,15 @@ class ISAParser(Grammar):
# They are all processed as they are seen. # They are all processed as they are seen.
def p_def_or_output(self, t): def p_def_or_output(self, t):
"""def_or_output : name_decl """def_or_output : name_decl
| def_format | def_format
| def_bitfield | def_bitfield
| def_bitfield_struct | def_bitfield_struct
| def_template | def_template
| def_operand_types | def_operand_types
| def_operands | def_operands
| output | output
| global_let | global_let
| split""" | split"""
# Utility function used by both invocations of splitting - explicit # Utility function used by both invocations of splitting - explicit
# 'split' keyword and split() function inside "let {{ }};" blocks. # 'split' keyword and split() function inside "let {{ }};" blocks.
@@ -992,8 +991,8 @@ class ISAParser(Grammar):
def p_output_type(self, t): def p_output_type(self, t):
"""output_type : DECODER """output_type : DECODER
| HEADER | HEADER
| EXEC""" | EXEC"""
t[0] = t[1] t[0] = t[1]
# ISA name declaration looks like "namespace <foo>;" # ISA name declaration looks like "namespace <foo>;"
@@ -1175,7 +1174,7 @@ del wrap
def p_param_list_1(self, t): def p_param_list_1(self, t):
"""param_list : positional_param_list """param_list : positional_param_list
| nonpositional_param_list""" | nonpositional_param_list"""
t[0] = t[1] t[0] = t[1]
def p_positional_param_list_0(self, t): def p_positional_param_list_0(self, t):
@@ -1196,7 +1195,7 @@ del wrap
def p_nonpositional_param_list_1(self, t): def p_nonpositional_param_list_1(self, t):
"""nonpositional_param_list : keyword_param_list """nonpositional_param_list : keyword_param_list
| excess_args_param""" | excess_args_param"""
t[0] = t[1] t[0] = t[1]
def p_keyword_param_list_0(self, t): def p_keyword_param_list_0(self, t):
@@ -1360,7 +1359,7 @@ StaticInstPtr
t[0] = ["default:"] t[0] = ["default:"]
def prep_int_lit_case_label(self, lit): def prep_int_lit_case_label(self, lit):
if lit >= 2 ** 32: if lit >= 2**32:
return "case %#xULL: " % lit return "case %#xULL: " % lit
else: else:
return "case %#x: " % lit return "case %#x: " % lit
@@ -1468,9 +1467,9 @@ StaticInstPtr
# #
def p_expr_0(self, t): def p_expr_0(self, t):
"""expr : ID """expr : ID
| INTLIT | INTLIT
| STRLIT | STRLIT
| CODELIT""" | CODELIT"""
t[0] = t[1] t[0] = t[1]
def p_expr_1(self, t): def p_expr_1(self, t):

View File

@@ -375,7 +375,7 @@ def p_file(t):
def p_opt_rom_or_macros_0(t): def p_opt_rom_or_macros_0(t):
"opt_rom_or_macros : " "opt_rom_or_macros :"
def p_opt_rom_or_macros_1(t): def p_opt_rom_or_macros_1(t):
@@ -392,7 +392,7 @@ def p_rom_or_macros_1(t):
def p_rom_or_macro_0(t): def p_rom_or_macro_0(t):
"""rom_or_macro : rom_block """rom_or_macro : rom_block
| macroop_def""" | macroop_def"""
# Defines a section of microcode that should go in the current ROM # Defines a section of microcode that should go in the current ROM
@@ -466,20 +466,20 @@ def p_statement(t):
# A statement can be a microop or an assembler directive # A statement can be a microop or an assembler directive
def p_content_of_statement_0(t): def p_content_of_statement_0(t):
"""content_of_statement : microop """content_of_statement : microop
| directive""" | directive"""
t[0] = t[1] t[0] = t[1]
# Ignore empty statements # Ignore empty statements
def p_content_of_statement_1(t): def p_content_of_statement_1(t):
"content_of_statement : " "content_of_statement :"
pass pass
# Statements are ended by newlines or a semi colon # Statements are ended by newlines or a semi colon
def p_end_of_statement(t): def p_end_of_statement(t):
"""end_of_statement : NEWLINE """end_of_statement : NEWLINE
| SEMI""" | SEMI"""
pass pass

View File

@@ -145,4 +145,3 @@ output decoder {{
} }
}}; }};

View File

@@ -2545,5 +2545,3 @@ decode OPCODE_HI default Unknown::unknown() {
0x6: CP2Unimpl::sdc2(); 0x6: CP2Unimpl::sdc2();
} }
} }

View File

@@ -326,7 +326,3 @@ def format Jump(code, *opt_flags) {{
decode_block = BasicDecode.subst(iop) decode_block = BasicDecode.subst(iop)
exec_output = BasicExecute.subst(iop) exec_output = BasicExecute.subst(iop)
}}; }};

View File

@@ -241,5 +241,3 @@ def format CP1Control(code, *flags) {{
decode_block = BasicDecode.subst(iop) decode_block = BasicDecode.subst(iop)
exec_output = CP1Execute.subst(iop) exec_output = CP1Execute.subst(iop)
}}; }};

View File

@@ -208,6 +208,3 @@ def format DspHiLoOp(code, *opt_flags) {{
exec_output = DspHiLoExecute.subst(iop) exec_output = DspHiLoExecute.subst(iop)
}}; }};

View File

@@ -363,4 +363,3 @@ def format FloatPSCompareOp(cond_code1, cond_code2, *flags) {{
decode_block = BasicDecode.subst(iop) decode_block = BasicDecode.subst(iop)
exec_output = BasicExecute.subst(iop) exec_output = BasicExecute.subst(iop)
}}; }};

View File

@@ -134,4 +134,3 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
def format Nop() {{ def format Nop() {{
decode_block = 'return new Nop(\"\",machInst);\n' decode_block = 'return new Nop(\"\",machInst);\n'
}}; }};

View File

@@ -273,4 +273,3 @@ def format WarnUnimpl() {{
iop = InstObjParams(name, 'WarnUnimplemented') iop = InstObjParams(name, 'WarnUnimplemented')
decode_block = BasicDecodeWithMnemonic.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop)
}}; }};

View File

@@ -77,4 +77,3 @@ output exec {{
def format Unknown() {{ def format Unknown() {{
decode_block = 'return new Unknown(machInst);\n' decode_block = 'return new Unknown(machInst);\n'
}}; }};

View File

@@ -141,4 +141,3 @@ def format WarnUnimpl() {{
iop = InstObjParams(name, 'WarnUnimplemented') iop = InstObjParams(name, 'WarnUnimplemented')
decode_block = BasicDecodeWithMnemonic.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop)
}}; }};

View File

@@ -82,4 +82,3 @@ output exec {{
def format Unknown() {{ def format Unknown() {{
decode_block = 'return new Unknown(machInst);\n' decode_block = 'return new Unknown(machInst);\n'
}}; }};

View File

@@ -224,5 +224,3 @@ output decoder {{
} }
}}; }};

View File

@@ -45,4 +45,4 @@
<reg name="t5" bitsize="64" type="int"/> <reg name="t5" bitsize="64" type="int"/>
<reg name="t6" bitsize="64" type="int"/> <reg name="t6" bitsize="64" type="int"/>
<reg name="pc" bitsize="64" type="code_ptr"/> <reg name="pc" bitsize="64" type="code_ptr"/>
</feature> </feature>

View File

@@ -245,4 +245,4 @@
<reg name="mucounteren" bitsize="64"/> <reg name="mucounteren" bitsize="64"/>
<reg name="mscounteren" bitsize="64"/> <reg name="mscounteren" bitsize="64"/>
<reg name="mhcounteren" bitsize="64"/> --> <reg name="mhcounteren" bitsize="64"/> -->
</feature> </feature>

View File

@@ -55,4 +55,4 @@
<reg name="frm" bitsize="32" type="int" regnum="67"/> <reg name="frm" bitsize="32" type="int" regnum="67"/>
<reg name="fcsr" bitsize="32" type="int" regnum="68"/> <reg name="fcsr" bitsize="32" type="int" regnum="68"/>
<reg name="placeholder" bitsize="32" type="int" regnum="69"/> <reg name="placeholder" bitsize="32" type="int" regnum="69"/>
</feature> </feature>

View File

@@ -10,4 +10,4 @@
<xi:include href="riscv-64bit-cpu.xml"/> <xi:include href="riscv-64bit-cpu.xml"/>
<xi:include href="riscv-64bit-fpu.xml"/> <xi:include href="riscv-64bit-fpu.xml"/>
<xi:include href="riscv-64bit-csr.xml"/> <xi:include href="riscv-64bit-csr.xml"/>
</target> </target>

View File

@@ -128,4 +128,4 @@ def bitfield M5FUNC <31:25>;
def bitfield BIT24 <24>; def bitfield BIT24 <24>;
def bitfield RNUM <23:20>; def bitfield RNUM <23:20>;
def bitfield KFUNCT5 <29:25>; def bitfield KFUNCT5 <29:25>;
def bitfield BS <31:30>; def bitfield BS <31:30>;

View File

@@ -132,5 +132,3 @@ output exec {{
} }
} }
}}; }};

View File

@@ -187,4 +187,3 @@ def format BranchSplit(code=default_branch_code,
decode_block) = doUncondBranch(name, Name, decode_block) = doUncondBranch(name, Name,
"BranchSplit", code, annul_code, opt_flags) "BranchSplit", code, annul_code, opt_flags)
}}; }};

View File

@@ -51,4 +51,3 @@
// Include the branch format // Include the branch format
##include "branch.isa" ##include "branch.isa"

View File

@@ -162,4 +162,3 @@ def format SetHi(code, *opt_flags) {{
exec_output = IntOpExecute.subst(iop) exec_output = IntOpExecute.subst(iop)
decode_block = SetHiDecode.subst(iop) decode_block = SetHiDecode.subst(iop)
}}; }};

View File

@@ -166,4 +166,3 @@ def format TwinLoad(code, *opt_flags) {{
AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck, AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck,
name, Name, "EXT_ASI", opt_flags) name, Name, "EXT_ASI", opt_flags)
}}; }};

View File

@@ -174,5 +174,3 @@ def format CasAlt(code, postacc_code, mem_flags, *opt_flags) {{
decode_block) = doCasFormat(code, SwapFuncs, AlternateASIPrivFaultCheck, decode_block) = doCasFormat(code, SwapFuncs, AlternateASIPrivFaultCheck,
name, Name, flags, ["IsStoreConditional"], postacc_code) name, Name, flags, ["IsStoreConditional"], postacc_code)
}}; }};

View File

@@ -133,4 +133,3 @@ def format HPriv(code, check_tl=false, *opt_flags) {{
doPrivFormat(code, check_code, name, Name, opt_flags, doPrivFormat(code, check_code, name, Name, opt_flags,
check_tl=(check_tl != 'false')) check_tl=(check_tl != 'false'))
}}; }};

View File

@@ -40,4 +40,3 @@ def format WarnUnimpl() {{
iop = InstObjParams(name, 'WarnUnimplemented') iop = InstObjParams(name, 'WarnUnimplemented')
decode_block = BasicDecodeWithMnemonic.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop)
}}; }};

View File

@@ -85,4 +85,3 @@ def format CPUIDInst(code, *opt_flags) {{
decode_block = BasicDecode.subst(iop) decode_block = BasicDecode.subst(iop)
exec_output = CPUIDExecute.subst(iop) exec_output = CPUIDExecute.subst(iop)
}}; }};

View File

@@ -54,4 +54,3 @@ def format M5InternalError(error_message) {{
iop.message = error_message iop.message = error_message
decode_block = ErrorDecode.subst(iop) decode_block = ErrorDecode.subst(iop)
}}; }};

View File

@@ -122,4 +122,3 @@ def format MwaitInst(code, *opt_flags) {{
exec_output += MwaitInitiateAcc.subst(iop) exec_output += MwaitInitiateAcc.subst(iop)
exec_output += MwaitCompleteAcc.subst(iop) exec_output += MwaitCompleteAcc.subst(iop)
}}; }};

View File

@@ -84,4 +84,3 @@ def format NopInst(*opt_flags) {{
decode_block = BasicDecode.subst(iop) decode_block = BasicDecode.subst(iop)
exec_output = NopExecute.subst(iop) exec_output = NopExecute.subst(iop)
}}; }};

View File

@@ -88,4 +88,3 @@ def format SyscallInst(code, *opt_flags) {{
decode_block = BasicDecode.subst(iop) decode_block = BasicDecode.subst(iop)
exec_output = SyscallExecute.subst(iop) exec_output = SyscallExecute.subst(iop)
}}; }};

View File

@@ -149,4 +149,3 @@ def format WarnUnimpl() {{
iop = InstObjParams(name, 'WarnUnimplemented') iop = InstObjParams(name, 'WarnUnimplemented')
decode_block = BasicDecodeWithMnemonic.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop)
}}; }};

View File

@@ -456,4 +456,3 @@ TEST(BitfieldTest, CountLeadingZero64AllZeros)
uint64_t value = 0; uint64_t value = 0;
EXPECT_EQ(64, clz64(value)); EXPECT_EQ(64, clz64(value));
} }

View File

@@ -100,4 +100,3 @@ MultiBitSel::hash(Addr addr, int hash_number) const
} // namespace bloom_filter } // namespace bloom_filter
} // namespace gem5 } // namespace gem5

View File

@@ -124,4 +124,4 @@ For more detail, please see the following paper:
T. Ta, X. Zhang, A. Gutierrez and B. M. Beckmann, "Autonomous Data-Race-Free T. Ta, X. Zhang, A. Gutierrez and B. M. Beckmann, "Autonomous Data-Race-Free
GPU Testing," 2019 IEEE International Symposium on Workload Characterization GPU Testing," 2019 IEEE International Symposium on Workload Characterization
(IISWC), Orlando, FL, USA, 2019, pp. 81-92, doi: (IISWC), Orlando, FL, USA, 2019, pp. 81-92, doi:
10.1109/IISWC47752.2019.9042019. 10.1109/IISWC47752.2019.9042019.

View File

@@ -68,4 +68,3 @@ if env['USE_PYTHON']:
SimObject('TrafficGen.py', sim_objects=['TrafficGen'], tags='protobuf') SimObject('TrafficGen.py', sim_objects=['TrafficGen'], tags='protobuf')
Source('trace_gen.cc', tags='protobuf') Source('trace_gen.cc', tags='protobuf')
Source('traffic_gen.cc', tags='protobuf') Source('traffic_gen.cc', tags='protobuf')

View File

@@ -39,7 +39,7 @@ from m5.objects.BaseCPU import BaseCPU
class TraceCPU(BaseCPU): class TraceCPU(BaseCPU):
"""Trace CPU model which replays traces generated in a prior simulation """Trace CPU model which replays traces generated in a prior simulation
using DerivO3CPU or its derived classes. It interfaces with L1 caches. using DerivO3CPU or its derived classes. It interfaces with L1 caches.
""" """
type = "TraceCPU" type = "TraceCPU"

View File

@@ -72,4 +72,3 @@ enum amdgpu_hwreg
} // namespace gem5 } // namespace gem5
#endif // __DEV_GPU_HWREG_DEFINES_H__ #endif // __DEV_GPU_HWREG_DEFINES_H__

View File

@@ -43,12 +43,12 @@ from m5.util.fdthelper import FdtNode, FdtProperty, FdtPropertyWords, FdtState
class SystemCounter(SimObject): class SystemCounter(SimObject):
""" """
Shared by both PE-implementations and memory-mapped timers. It provides a Shared by both PE-implementations and memory-mapped timers. It provides a
uniform view of system time through its counter value. uniform view of system time through its counter value.
Reference: Reference:
Arm ARM (ARM DDI 0487E.a) Arm ARM (ARM DDI 0487E.a)
D11.1.2 - The system counter D11.1.2 - The system counter
""" """
type = "SystemCounter" type = "SystemCounter"
@@ -71,14 +71,14 @@ Reference:
class GenericTimer(SimObject): class GenericTimer(SimObject):
""" """
Architected timers per PE in the system. Each of them provides a physical Architected timers per PE in the system. Each of them provides a physical
counter, a virtual counter and several timers accessible from different counter, a virtual counter and several timers accessible from different
exception levels and security states. exception levels and security states.
Reference: Reference:
Arm ARM (ARM DDI 0487E.a) Arm ARM (ARM DDI 0487E.a)
D11.2 - The AArch64 view of the Generic Timer D11.2 - The AArch64 view of the Generic Timer
G6.2 - The AArch32 view of the Generic Timer G6.2 - The AArch32 view of the Generic Timer
""" """
type = "GenericTimer" type = "GenericTimer"
@@ -135,12 +135,12 @@ Reference:
class GenericTimerFrame(PioDevice): class GenericTimerFrame(PioDevice):
""" """
Memory-mapped timer frame implementation. Controlled from GenericTimerMem, Memory-mapped timer frame implementation. Controlled from GenericTimerMem,
may be used by peripherals without a system register interface. may be used by peripherals without a system register interface.
Reference: Reference:
Arm ARM (ARM DDI 0487E.a) Arm ARM (ARM DDI 0487E.a)
I2.3.2 - The CNTBaseN and CNTEL0BaseN frames I2.3.2 - The CNTBaseN and CNTEL0BaseN frames
""" """
type = "GenericTimerFrame" type = "GenericTimerFrame"
@@ -178,16 +178,16 @@ Reference:
class GenericTimerMem(PioDevice): class GenericTimerMem(PioDevice):
""" """
System level implementation. It provides three main components: System level implementation. It provides three main components:
- Memory-mapped counter module: controls the system timer through the - Memory-mapped counter module: controls the system timer through the
CNTControlBase frame, and provides its value through the CNTReadBase frame CNTControlBase frame, and provides its value through the CNTReadBase frame
- Memory-mapped timer control module: controls the memory-mapped timers - Memory-mapped timer control module: controls the memory-mapped timers
- Memory-mapped timers: implementations of the GenericTimer for system - Memory-mapped timers: implementations of the GenericTimer for system
peripherals peripherals
Reference: Reference:
Arm ARM (ARM DDI 0487E.a) Arm ARM (ARM DDI 0487E.a)
I2 - System Level Implementation of the Generic Timer I2 - System Level Implementation of the Generic Timer
""" """
type = "GenericTimerMem" type = "GenericTimerMem"

View File

@@ -339,9 +339,9 @@ class RealViewTemperatureSensor(SimObject):
class VExpressMCC(SubSystem): class VExpressMCC(SubSystem):
"""ARM V2M-P1 Motherboard Configuration Controller """ARM V2M-P1 Motherboard Configuration Controller
This subsystem describes a subset of the devices that sit behind the This subsystem describes a subset of the devices that sit behind the
motherboard configuration controller on the the ARM Motherboard motherboard configuration controller on the the ARM Motherboard
Express (V2M-P1) motherboard. See ARM DUI 0447J for details. Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
""" """
class Osc(RealViewOsc): class Osc(RealViewOsc):
@@ -380,9 +380,9 @@ Express (V2M-P1) motherboard. See ARM DUI 0447J for details.
class CoreTile2A15DCC(SubSystem): class CoreTile2A15DCC(SubSystem):
"""ARM CoreTile Express A15x2 Daughterboard Configuration Controller """ARM CoreTile Express A15x2 Daughterboard Configuration Controller
This subsystem describes a subset of the devices that sit behind the This subsystem describes a subset of the devices that sit behind the
daughterboard configuration controller on a CoreTile Express A15x2. See daughterboard configuration controller on a CoreTile Express A15x2. See
ARM DUI 0604E for details. ARM DUI 0604E for details.
""" """
class Osc(RealViewOsc): class Osc(RealViewOsc):
@@ -491,10 +491,10 @@ class Sp804(AmbaPioDevice):
class Sp805(AmbaIntDevice): class Sp805(AmbaIntDevice):
""" """
Arm Watchdog Module (SP805) Arm Watchdog Module (SP805)
Reference: Reference:
Arm Watchdog Module (SP805) - Technical Reference Manual - rev. r1p0 Arm Watchdog Module (SP805) - Technical Reference Manual - rev. r1p0
Doc. ID: ARM DDI 0270B Doc. ID: ARM DDI 0270B
""" """
type = "Sp805" type = "Sp805"
@@ -746,10 +746,10 @@ class MmioSRAM(ParentMem):
class FVPBasePwrCtrl(BasicPioDevice): class FVPBasePwrCtrl(BasicPioDevice):
""" """
Based on Fast Models Base_PowerController v11.8 Based on Fast Models Base_PowerController v11.8
Reference: Reference:
Fast Models Reference Manual - Section 7.7.2 - Version 11.8 Fast Models Reference Manual - Section 7.7.2 - Version 11.8
Document ID: 100964_1180_00_en Document ID: 100964_1180_00_en
""" """
type = "FVPBasePwrCtrl" type = "FVPBasePwrCtrl"
@@ -1100,148 +1100,148 @@ class VExpress_EMM64(VExpress_EMM):
class VExpress_GEM5_Base(RealView): class VExpress_GEM5_Base(RealView):
""" """
The VExpress gem5 memory map is loosely based on a modified The VExpress gem5 memory map is loosely based on a modified
Versatile Express RS1 memory map. Versatile Express RS1 memory map.
The gem5 platform has been designed to implement a subset of the The gem5 platform has been designed to implement a subset of the
original Versatile Express RS1 memory map. Off-chip peripherals should, original Versatile Express RS1 memory map. Off-chip peripherals should,
when possible, adhere to the Versatile Express memory map. Non-PCI when possible, adhere to the Versatile Express memory map. Non-PCI
off-chip devices that are gem5-specific should live in the CS5 memory off-chip devices that are gem5-specific should live in the CS5 memory
space to avoid conflicts with existing devices that we might want to space to avoid conflicts with existing devices that we might want to
model in the future. Such devices should normally have interrupts in model in the future. Such devices should normally have interrupts in
the gem5-specific SPI range. the gem5-specific SPI range.
On-chip peripherals are loosely modeled after the ARM CoreTile Express On-chip peripherals are loosely modeled after the ARM CoreTile Express
A15x2 memory and interrupt map. In particular, the GIC and A15x2 memory and interrupt map. In particular, the GIC and
Generic Timer have the same interrupt lines and base addresses. Other Generic Timer have the same interrupt lines and base addresses. Other
on-chip devices are gem5 specific. on-chip devices are gem5 specific.
Unlike the original Versatile Express RS2 extended platform, gem5 implements a Unlike the original Versatile Express RS2 extended platform, gem5 implements a
large contigious DRAM space, without aliases or holes, starting at the large contigious DRAM space, without aliases or holes, starting at the
2GiB boundary. This means that PCI memory is limited to 1GiB. 2GiB boundary. This means that PCI memory is limited to 1GiB.
References: References:
Technical Reference Manuals: Technical Reference Manuals:
Arm Motherboard Express uATX (V2M-P1) - ARM DUI 0447J Arm Motherboard Express uATX (V2M-P1) - ARM DUI 0447J
Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
Official Linux device tree specifications: Official Linux device tree specifications:
V2M-P1 - arch/arm/boot/dts/vexpress-v2m-rs1.dtsi V2M-P1 - arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
V2P-CA15 - arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts V2P-CA15 - arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
Memory map:
Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E
Daughterboard (global)
Section 3.2.1 - Table 3-1 - Daughterboard memory map
On-chip
Section 3.2.3 - Table 3-2 - Cortex-A15 MPCore on-chip peripheral
memory map
Interrupts:
Armv8-A Foundation Platform - User Guide - Version 11.8
Document ID: 100961_1180_00_en
Memory map: Memory map:
Arm CoreTile Express A15x2 (V2P-CA15) - ARM DUI 0604E 0x00000000-0x03ffffff: Boot memory (CS0)
Daughterboard (global) 0x04000000-0x07ffffff: Trusted Memory/Reserved
Section 3.2.1 - Table 3-1 - Daughterboard memory map 0x04000000-0x0403FFFF: 256kB Trusted SRAM
On-chip 0x06000000-0x07ffffff: 32MB Trusted DRAM
Section 3.2.3 - Table 3-2 - Cortex-A15 MPCore on-chip peripheral 0x08000000-0x0bffffff: NOR FLASH0 (CS0 alias)
memory map 0x0c000000-0x0fffffff: NOR FLASH1 (Off-chip, CS4)
0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5)
0x10000000-0x1000ffff: gem5 energy controller
0x10010000-0x1001ffff: gem5 pseudo-ops
0x10020000-0x1002ffff: gem5 MHU
0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1)
0x18000000-0x1bffffff: Off-chip, Peripherals, CS2
0x18000000-0x19ffffff: VRAM
0x1a000000-0x1bffffff: Reserved
0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3):
0x1c010000-0x1c01ffff: realview_io (VE system control regs.)
0x1c060000-0x1c06ffff: KMI0 (keyboard)
0x1c070000-0x1c07ffff: KMI1 (mouse)
0x1c090000-0x1c09ffff: UART0
0x1c0a0000-0x1c0affff: UART1
0x1c0b0000-0x1c0bffff: UART2
0x1c0c0000-0x1c0cffff: UART3
0x1c0f0000-0x1c0fffff: Watchdog (SP805)
0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension)
0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension)
0x1c170000-0x1c17ffff: RTC
0x20000000-0x3fffffff: On-chip peripherals:
0x2a430000-0x2a43ffff: System Counter (control)
0x2a490000-0x2a49ffff: Trusted Watchdog (SP805)
0x2a800000-0x2a800fff: System Counter (read)
0x2a810000-0x2a810fff: System Timer (control)
0x2a820000-0x2a820fff: System Timer (frame 0)
0x2a830000-0x2a830fff: System Timer (frame 1)
0x2b000000-0x2b00ffff: HDLCD
0x2b060000-0x2b060fff: System Watchdog (SP805)
0x2b400000-0x2b41ffff: SMMUv3
0x2c001000-0x2c001fff: GIC (distributor)
0x2c002000-0x2c003fff: GIC (CPU interface)
0x2c004000-0x2c005fff: vGIC (HV)
0x2c006000-0x2c007fff: vGIC (VCPU)
0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
0x2d000000-0x2d00ffff: GPU (reserved)
0x2e000000-0x2e007fff: Non-trusted SRAM
0x2f000000-0x2fffffff: PCI IO space
0x30000000-0x3fffffff: PCI config space
0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
0x80000000-X: DRAM
Interrupts: Interrupts:
Armv8-A Foundation Platform - User Guide - Version 11.8 0- 15: Software generated interrupts (SGIs)
Document ID: 100961_1180_00_en 16- 31: On-chip private peripherals (PPIs)
19 : generic_timer (virt sec EL2)
Memory map: 20 : generic_timer (phys sec EL2)
0x00000000-0x03ffffff: Boot memory (CS0) 25 : vgic
0x04000000-0x07ffffff: Trusted Memory/Reserved 26 : generic_timer (phys non-sec EL2)
0x04000000-0x0403FFFF: 256kB Trusted SRAM 27 : generic_timer (virt EL1)
0x06000000-0x07ffffff: 32MB Trusted DRAM 28 : generic_timer (virt non-sec EL2)
0x08000000-0x0bffffff: NOR FLASH0 (CS0 alias) 29 : generic_timer (phys EL3)
0x0c000000-0x0fffffff: NOR FLASH1 (Off-chip, CS4) 30 : generic_timer (phys EL1)
0x10000000-0x13ffffff: gem5-specific peripherals (Off-chip, CS5) 31 : Reserved (Legacy IRQ)
0x10000000-0x1000ffff: gem5 energy controller 32- 95: Mother board peripherals (SPIs)
0x10010000-0x1001ffff: gem5 pseudo-ops 32 : Watchdog (SP805)
0x10020000-0x1002ffff: gem5 MHU 33 : Reserved (IOFPGA SW int)
34-35: Reserved (SP804)
0x14000000-0x17ffffff: Reserved (Off-chip, PSRAM, CS1) 36 : RTC
37-40: uart0-uart3
0x18000000-0x1bffffff: Off-chip, Peripherals, CS2 41-42: Reserved (PL180)
0x18000000-0x19ffffff: VRAM 43 : Reserved (AACI)
0x1a000000-0x1bffffff: Reserved 44-45: kmi0-kmi1
46 : Reserved (CLCD)
0x1c000000-0x1fffffff: Peripheral block 1 (Off-chip, CS3): 47 : Reserved (Ethernet)
0x1c010000-0x1c01ffff: realview_io (VE system control regs.) 48 : Reserved (USB)
0x1c060000-0x1c06ffff: KMI0 (keyboard) 56 : Trusted Watchdog (SP805)
0x1c070000-0x1c07ffff: KMI1 (mouse) 57 : System timer0 (phys)
0x1c090000-0x1c09ffff: UART0 58 : System timer1 (phys)
0x1c0a0000-0x1c0affff: UART1 95-255: On-chip interrupt sources (we use these for
0x1c0b0000-0x1c0bffff: UART2 gem5-specific devices, SPIs)
0x1c0c0000-0x1c0cffff: UART3 74 : VirtIO (gem5/FM extension)
0x1c0f0000-0x1c0fffff: Watchdog (SP805) 75 : VirtIO (gem5/FM extension)
0x1c130000-0x1c13ffff: VirtIO (gem5/FM extension) 95 : HDLCD
0x1c140000-0x1c14ffff: VirtIO (gem5/FM extension) 96- 98: GPU (reserved)
0x1c170000-0x1c17ffff: RTC 100-103: PCI
130 : System Watchdog (SP805)
0x20000000-0x3fffffff: On-chip peripherals: 256-319: MSI frame 0 (gem5-specific, SPIs)
0x2a430000-0x2a43ffff: System Counter (control) 320-511: Unused
0x2a490000-0x2a49ffff: Trusted Watchdog (SP805)
0x2a800000-0x2a800fff: System Counter (read)
0x2a810000-0x2a810fff: System Timer (control)
0x2a820000-0x2a820fff: System Timer (frame 0)
0x2a830000-0x2a830fff: System Timer (frame 1)
0x2b000000-0x2b00ffff: HDLCD
0x2b060000-0x2b060fff: System Watchdog (SP805)
0x2b400000-0x2b41ffff: SMMUv3
0x2c001000-0x2c001fff: GIC (distributor)
0x2c002000-0x2c003fff: GIC (CPU interface)
0x2c004000-0x2c005fff: vGIC (HV)
0x2c006000-0x2c007fff: vGIC (VCPU)
0x2c1c0000-0x2c1cffff: GICv2m MSI frame 0
0x2d000000-0x2d00ffff: GPU (reserved)
0x2e000000-0x2e007fff: Non-trusted SRAM
0x2f000000-0x2fffffff: PCI IO space
0x30000000-0x3fffffff: PCI config space
0x40000000-0x7fffffff: Ext. AXI: Used as PCI memory
0x80000000-X: DRAM
Interrupts:
0- 15: Software generated interrupts (SGIs)
16- 31: On-chip private peripherals (PPIs)
19 : generic_timer (virt sec EL2)
20 : generic_timer (phys sec EL2)
25 : vgic
26 : generic_timer (phys non-sec EL2)
27 : generic_timer (virt EL1)
28 : generic_timer (virt non-sec EL2)
29 : generic_timer (phys EL3)
30 : generic_timer (phys EL1)
31 : Reserved (Legacy IRQ)
32- 95: Mother board peripherals (SPIs)
32 : Watchdog (SP805)
33 : Reserved (IOFPGA SW int)
34-35: Reserved (SP804)
36 : RTC
37-40: uart0-uart3
41-42: Reserved (PL180)
43 : Reserved (AACI)
44-45: kmi0-kmi1
46 : Reserved (CLCD)
47 : Reserved (Ethernet)
48 : Reserved (USB)
56 : Trusted Watchdog (SP805)
57 : System timer0 (phys)
58 : System timer1 (phys)
95-255: On-chip interrupt sources (we use these for
gem5-specific devices, SPIs)
74 : VirtIO (gem5/FM extension)
75 : VirtIO (gem5/FM extension)
95 : HDLCD
96- 98: GPU (reserved)
100-103: PCI
130 : System Watchdog (SP805)
256-319: MSI frame 0 (gem5-specific, SPIs)
320-511: Unused
""" """

View File

@@ -84,4 +84,3 @@ class A9SCU : public BasicPioDevice
} // namespace gem5 } // namespace gem5
#endif // __DEV_ARM_A9SCU_HH__ #endif // __DEV_ARM_A9SCU_HH__

Some files were not shown because too many files have changed in this diff Show More