Merge ARM into the head. ARM will compile but may not actually work.

This commit is contained in:
Gabe Black 2009-04-06 10:19:36 -07:00
commit d080581db1
1238 changed files with 77272 additions and 36447 deletions

View file

@ -16,3 +16,5 @@ b174ae14f007ba0c341f8df77d36f57f48369cc8 m5_2.0_beta2
91a9ac67662aa3a79315ade29b17a85961fecd88 m5_2.0_beta3
dce5a8655829b7d2e24ce40cafc9c8873a71671f m5_2.0_beta5
1ac44b6c87ec71a8410c9a9c219269eca71f8077 m5_2.0_beta4
60a931b03fb165807f02bcccc4f7d0fd705a67a9 copyright_update
d8b246a665c160a31751b4091f097022cde16dd7 m5_2.0_beta6

2
README
View file

@ -1,4 +1,4 @@
This is release 2.0_beta5 of the M5 simulator.
This is release 2.0_beta6 of the M5 simulator.
For detailed information about building the simulator and getting
started please refer to http://www.m5sim.org.

View file

@ -1,13 +1,26 @@
October 6, 2008: m5_2.0_beta6
--------------------
New Features
1. Support for gcc 4.3
2. Core m5 code in libm5 for integration with other simulators
3. Preliminary support for X86 SE mode
4. Additional system calls emulated
5. m5term updated to work on OS X
6. Ability to disable listen sockets
7. Event queue performance improvements and rewrite
8. Better errors for unconnected memory ports
Bug fixes
1. ALPHA_SE O3 perlbmk benchmark
2. Translation bug where O3 could fetch from uncachable memory
3. Many minor bugs
Outstanding issues for 2.0 release:
--------------------
1. Fix O3 CPU bug in SE 40.perlbmk fails
2. Fix O3 processing nacks/coherence messages
3. Better statistics for the caches.
4. FS mode doesn't work under Cygwin
5. memtest regression crashes under Cygwin
6. Make repository public
7. Testing
8. Validation
1. Statistics cleanup
2. Improve regression system
3. Testing
4. Validation
March 1, 2008: m5_2.0_beta5
--------------------

View file

@ -1,5 +1,6 @@
# -*- mode:python -*-
# Copyright (c) 2009 The Hewlett-Packard Development Company
# Copyright (c) 2004-2005 The Regents of The University of Michigan
# All rights reserved.
#
@ -27,6 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Steve Reinhardt
# Nathan Binkert
###################################################
#
@ -63,51 +65,126 @@
#
###################################################
import sys
import os
# Check for recent-enough Python and SCons versions.
try:
# Really old versions of scons only take two options for the
# function, so check once without the revision and once with the
# revision, the first instance will fail for stuff other than
# 0.98, and the second will fail for 0.98.0
EnsureSConsVersion(0, 98)
EnsureSConsVersion(0, 98, 1)
except SystemExit, e:
print """
For more details, see:
http://m5sim.org/wiki/index.php/Compiling_M5
"""
raise
from os.path import isdir, isfile, join as joinpath
# We ensure the python version early because we have stuff that
# requires python 2.4
try:
EnsurePythonVersion(2, 4)
except SystemExit, e:
print """
You can use a non-default installation of the Python interpreter by
either (1) rearranging your PATH so that scons finds the non-default
'python' first or (2) explicitly invoking an alternative interpreter
on the scons script.
For more details, see:
http://m5sim.org/wiki/index.php/Using_a_non-default_Python_installation
"""
raise
import os
import re
import subprocess
import sys
from os import mkdir, environ
from os.path import abspath, basename, dirname, expanduser, normpath
from os.path import exists, isdir, isfile
from os.path import join as joinpath, split as splitpath
import SCons
import SCons.Node
# Check for recent-enough Python and SCons versions. If your system's
# default installation of Python is not recent enough, you can use a
# non-default installation of the Python interpreter by either (1)
# rearranging your PATH so that scons finds the non-default 'python'
# first or (2) explicitly invoking an alternative interpreter on the
# scons script, e.g., "/usr/local/bin/python2.4 `which scons` [args]".
EnsurePythonVersion(2,4)
def read_command(cmd, **kwargs):
"""run the command cmd, read the results and return them
this is sorta like `cmd` in shell"""
from subprocess import Popen, PIPE, STDOUT
# Import subprocess after we check the version since it doesn't exist in
# Python < 2.4.
import subprocess
if isinstance(cmd, str):
cmd = cmd.split()
# Ironically, SCons 0.96 dies if you give EnsureSconsVersion a
# 3-element version number.
min_scons_version = (0,96,91)
no_exception = 'exception' in kwargs
exception = kwargs.pop('exception', None)
kwargs.setdefault('shell', False)
kwargs.setdefault('stdout', PIPE)
kwargs.setdefault('stderr', STDOUT)
kwargs.setdefault('close_fds', True)
try:
EnsureSConsVersion(*min_scons_version)
except:
print "Error checking current SCons version."
print "SCons", ".".join(map(str,min_scons_version)), "or greater required."
Exit(2)
subp = Popen(cmd, **kwargs)
except Exception, e:
if no_exception:
return exception
raise
return subp.communicate()[0]
# The absolute path to the current directory (where this file lives).
ROOT = Dir('.').abspath
# helper function: compare arrays or strings of version numbers.
# E.g., compare_version((1,3,25), (1,4,1)')
# returns -1, 0, 1 if v1 is <, ==, > v2
def compare_versions(v1, v2):
def make_version_list(v):
if isinstance(v, (list,tuple)):
return v
elif isinstance(v, str):
return map(lambda x: int(re.match('\d+', x).group()), v.split('.'))
else:
raise TypeError
# Path to the M5 source tree.
SRCDIR = joinpath(ROOT, 'src')
v1 = make_version_list(v1)
v2 = make_version_list(v2)
# Compare corresponding elements of lists
for n1,n2 in zip(v1, v2):
if n1 < n2: return -1
if n1 > n2: return 1
# all corresponding values are equal... see if one has extra values
if len(v1) < len(v2): return -1
if len(v1) > len(v2): return 1
return 0
# tell python where to find m5 python code
sys.path.append(joinpath(ROOT, 'src/python'))
########################################################################
#
# Set up the base build environment.
#
########################################################################
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH',
'RANLIB' ])
def check_style_hook(ui):
ui.readconfig(joinpath(ROOT, '.hg', 'hgrc'))
style_hook = ui.config('hooks', 'pretxncommit.style', None)
use_env = {}
for key,val in os.environ.iteritems():
if key in use_vars or key.startswith("M5"):
use_env[key] = val
if not style_hook:
print """\
env = Environment(ENV=use_env)
env.root = Dir(".") # The current directory (where this file lives).
env.srcdir = Dir("src") # The source directory
########################################################################
#
# Mercurial Stuff.
#
# If the M5 directory is a mercurial repository, we should do some
# extra things.
#
########################################################################
hgdir = env.root.Dir(".hg")
mercurial_style_message = """
You're missing the M5 style hook.
Please install the hook so we can ensure that all code fits a common style.
@ -120,15 +197,49 @@ style = %s/util/style.py
[hooks]
pretxncommit.style = python:style.check_whitespace
""" % (ROOT)
sys.exit(1)
""" % (env.root)
if ARGUMENTS.get('IGNORE_STYLE') != 'True' and isdir(joinpath(ROOT, '.hg')):
mercurial_bin_not_found = """
Mercurial binary cannot be found, unfortunately this means that we
cannot easily determine the version of M5 that you are running and
this makes error messages more difficult to collect. Please consider
installing mercurial if you choose to post an error message
"""
mercurial_lib_not_found = """
Mercurial libraries cannot be found, ignoring style hook
If you are actually a M5 developer, please fix this and
run the style hook. It is important.
"""
hg_info = "Unknown"
if hgdir.exists():
# 1) Grab repository revision if we know it.
cmd = "hg id -n -i -t -b"
try:
hg_info = read_command(cmd, cwd=env.root.abspath).strip()
except OSError:
print mercurial_bin_not_found
# 2) Ensure that the style hook is in place.
try:
ui = None
if ARGUMENTS.get('IGNORE_STYLE') != 'True':
from mercurial import ui
check_style_hook(ui.ui())
ui = ui.ui()
except ImportError:
pass
print mercurial_lib_not_found
if ui is not None:
ui.readconfig(hgdir.File('hgrc').abspath)
style_hook = ui.config('hooks', 'pretxncommit.style', None)
if not style_hook:
print mercurial_style_message
sys.exit(1)
else:
print ".hg directory not found"
env['HG_INFO'] = hg_info
###################################################
#
@ -138,7 +249,7 @@ if ARGUMENTS.get('IGNORE_STYLE') != 'True' and isdir(joinpath(ROOT, '.hg')):
###################################################
# Find default configuration & binary.
Default(os.environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug'))
Default(environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug'))
# helper function: find last occurrence of element in list
def rfind(l, elt, offs = -1):
@ -147,22 +258,6 @@ def rfind(l, elt, offs = -1):
return i
raise ValueError, "element not found"
# helper function: compare dotted version numbers.
# E.g., compare_version('1.3.25', '1.4.1')
# returns -1, 0, 1 if v1 is <, ==, > v2
def compare_versions(v1, v2):
# Convert dotted strings to lists
v1 = map(int, v1.split('.'))
v2 = map(int, v2.split('.'))
# Compare corresponding elements of lists
for n1,n2 in zip(v1, v2):
if n1 < n2: return -1
if n1 > n2: return 1
# all corresponding values are equal... see if one has extra values
if len(v1) < len(v2): return -1
if len(v1) > len(v2): return 1
return 0
# Each target must have 'build' in the interior of the path; the
# directory below this will determine the build parameters. For
# example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we
@ -174,17 +269,17 @@ if COMMAND_LINE_TARGETS:
# Ask SCons which directory it was invoked from
launch_dir = GetLaunchDir()
# Make targets relative to invocation directory
abs_targets = map(lambda x: os.path.normpath(joinpath(launch_dir, str(x))),
COMMAND_LINE_TARGETS)
abs_targets = [ normpath(joinpath(launch_dir, str(x))) for x in \
COMMAND_LINE_TARGETS]
else:
# Default targets are relative to root of tree
abs_targets = map(lambda x: os.path.normpath(joinpath(ROOT, str(x))),
DEFAULT_TARGETS)
abs_targets = [ normpath(joinpath(ROOT, str(x))) for x in \
DEFAULT_TARGETS]
# Generate a list of the unique build roots and configs that the
# collected targets reference.
build_paths = []
variant_paths = []
build_root = None
for t in abs_targets:
path_dirs = t.split('/')
@ -201,24 +296,13 @@ for t in abs_targets:
print "Error: build targets not under same build root\n"\
" %s\n %s" % (build_root, this_build_root)
Exit(1)
build_path = joinpath('/',*path_dirs[:build_top+2])
if build_path not in build_paths:
build_paths.append(build_path)
variant_path = joinpath('/',*path_dirs[:build_top+2])
if variant_path not in variant_paths:
variant_paths.append(variant_path)
# Make sure build_root exists (might not if this is the first build there)
if not isdir(build_root):
os.mkdir(build_root)
###################################################
#
# Set up the default build environment. This environment is copied
# and modified according to each selected configuration.
#
###################################################
env = Environment(ENV = os.environ, # inherit user's environment vars
ROOT = ROOT,
SRCDIR = SRCDIR)
mkdir(build_root)
Export('env')
@ -230,22 +314,16 @@ env.SConsignFile(joinpath(build_root,"sconsign"))
# (soft) links work better.
env.SetOption('duplicate', 'soft-copy')
# I waffle on this setting... it does avoid a few painful but
# unnecessary builds, but it also seems to make trivial builds take
# noticeably longer.
if False:
env.TargetSignatures('content')
#
# Set up global sticky options... these are common to an entire build
# Set up global sticky variables... these are common to an entire build
# tree (not specific to a particular build like ALPHA_SE)
#
# Option validators & converters for global sticky options
# Variable validators & converters for global sticky variables
def PathListMakeAbsolute(val):
if not val:
return val
f = lambda p: os.path.abspath(os.path.expanduser(p))
f = lambda p: abspath(expanduser(p))
return ':'.join(map(f, val.split(':')))
def PathListAllExist(key, val, env):
@ -256,65 +334,67 @@ def PathListAllExist(key, val, env):
if not isdir(path):
raise SCons.Errors.UserError("Path does not exist: '%s'" % path)
global_sticky_opts_file = joinpath(build_root, 'options.global')
global_sticky_vars_file = joinpath(build_root, 'variables.global')
global_sticky_opts = Options(global_sticky_opts_file, args=ARGUMENTS)
global_sticky_vars = Variables(global_sticky_vars_file, args=ARGUMENTS)
global_sticky_opts.AddOptions(
('CC', 'C compiler', os.environ.get('CC', env['CC'])),
('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])),
global_sticky_vars.AddVariables(
('CC', 'C compiler', environ.get('CC', env['CC'])),
('CXX', 'C++ compiler', environ.get('CXX', env['CXX'])),
('BATCH', 'Use batch pool for build and tests', False),
('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
('EXTRAS', 'Add Extra directories to the compilation', '',
PathListAllExist, PathListMakeAbsolute)
)
# base help text
help_text = '''
Usage: scons [scons options] [build options] [target(s)]
Global sticky options:
'''
help_text += "Global sticky options:\n" \
+ global_sticky_opts.GenerateHelpText(env)
help_text += global_sticky_vars.GenerateHelpText(env)
# Update env with values from ARGUMENTS & file global_sticky_opts_file
global_sticky_opts.Update(env)
# Update env with values from ARGUMENTS & file global_sticky_vars_file
global_sticky_vars.Update(env)
# Save sticky option settings back to current options file
global_sticky_opts.Save(global_sticky_opts_file, env)
# Save sticky variable settings back to current variables file
global_sticky_vars.Save(global_sticky_vars_file, env)
# Parse EXTRAS option to build list of all directories where we're
# Parse EXTRAS variable to build list of all directories where we're
# look for sources etc. This list is exported as base_dir_list.
base_dir_list = [joinpath(ROOT, 'src')]
base_dir = env.srcdir.abspath
if env['EXTRAS']:
base_dir_list += env['EXTRAS'].split(':')
extras_dir_list = env['EXTRAS'].split(':')
else:
extras_dir_list = []
Export('base_dir_list')
Export('base_dir')
Export('extras_dir_list')
# the ext directory should be on the #includes path
env.Append(CPPPATH=[Dir('ext')])
# M5_PLY is used by isa_parser.py to find the PLY package.
env.Append(ENV = { 'M5_PLY' : str(Dir('ext/ply')) })
env['GCC'] = False
env['SUNCC'] = False
env['ICC'] = False
env['GCC'] = subprocess.Popen(env['CXX'] + ' --version', shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
close_fds=True).communicate()[0].find('GCC') >= 0
env['SUNCC'] = subprocess.Popen(env['CXX'] + ' -V', shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
close_fds=True).communicate()[0].find('Sun C++') >= 0
env['ICC'] = subprocess.Popen(env['CXX'] + ' -V', shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
close_fds=True).communicate()[0].find('Intel') >= 0
env.Append(ENV = { 'M5_PLY' : Dir('ext/ply').abspath })
CXX_version = read_command([env['CXX'],'--version'], exception=False)
CXX_V = read_command([env['CXX'],'-V'], exception=False)
env['GCC'] = CXX_version and CXX_version.find('g++') >= 0
env['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
env['ICC'] = CXX_V and CXX_V.find('Intel') >= 0
if env['GCC'] + env['SUNCC'] + env['ICC'] > 1:
print 'Error: How can we have two at the same time?'
Exit(1)
# Set up default C++ compiler flags
if env['GCC']:
env.Append(CCFLAGS='-pipe')
env.Append(CCFLAGS='-fno-strict-aliasing')
env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
env.Append(CXXFLAGS='-Wno-deprecated')
elif env['ICC']:
pass #Fix me... add warning flags once we clean up icc warnings
elif env['SUNCC']:
@ -329,10 +409,18 @@ else:
print ' Please fix SConstruct and src/SConscript and try again.'
Exit(1)
# Do this after we save setting back, or else we'll tack on an
# extra 'qdo' every time we run scons.
if env['BATCH']:
env['CC'] = env['BATCH_CMD'] + ' ' + env['CC']
env['CXX'] = env['BATCH_CMD'] + ' ' + env['CXX']
env['AS'] = env['BATCH_CMD'] + ' ' + env['AS']
env['AR'] = env['BATCH_CMD'] + ' ' + env['AR']
env['RANLIB'] = env['BATCH_CMD'] + ' ' + env['RANLIB']
if sys.platform == 'cygwin':
# cygwin has some header file issues...
env.Append(CCFLAGS=Split("-Wno-uninitialized"))
env.Append(CPPPATH=[Dir('ext/dnet')])
# Check for SWIG
if not env.has_key('SWIG'):
@ -341,7 +429,7 @@ if not env.has_key('SWIG'):
Exit(1)
# Check for appropriate SWIG version
swig_version = os.popen('swig -version').read().split()
swig_version = read_command(('swig', '-version'), exception='').split()
# First 3 words should be "SWIG Version x.y.z"
if len(swig_version) < 3 or \
swig_version[0] != 'SWIG' or swig_version[1] != 'Version':
@ -379,25 +467,53 @@ scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re))
# replace the scanners list that has what we want
env['SCANNERS'] = scanners
# Add a custom Check function to the Configure context so that we can
# figure out if the compiler adds leading underscores to global
# variables. This is needed for the autogenerated asm files that we
# use for embedding the python code.
def CheckLeading(context):
context.Message("Checking for leading underscore in global variables...")
# 1) Define a global variable called x from asm so the C compiler
# won't change the symbol at all.
# 2) Declare that variable.
# 3) Use the variable
#
# If the compiler prepends an underscore, this will successfully
# link because the external symbol 'x' will be called '_x' which
# was defined by the asm statement. If the compiler does not
# prepend an underscore, this will not successfully link because
# '_x' will have been defined by assembly, while the C portion of
# the code will be trying to use 'x'
ret = context.TryLink('''
asm(".globl _x; _x: .byte 0");
extern int x;
int main() { return x; }
''', extension=".c")
context.env.Append(LEADING_UNDERSCORE=ret)
context.Result(ret)
return ret
# Platform-specific configuration. Note again that we assume that all
# builds under a given build root run on the same host platform.
conf = Configure(env,
conf_dir = joinpath(build_root, '.scons_config'),
log_file = joinpath(build_root, 'scons_config.log'))
log_file = joinpath(build_root, 'scons_config.log'),
custom_tests = { 'CheckLeading' : CheckLeading })
# Check for leading underscores. Don't really need to worry either
# way so don't need to check the return code.
conf.CheckLeading()
# Check if we should compile a 64 bit binary on Mac OS X/Darwin
try:
import platform
uname = platform.uname()
if uname[0] == 'Darwin' and compare_versions(uname[2], '9.0.0') >= 0:
if int(subprocess.Popen('sysctl -n hw.cpu64bit_capable', shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
close_fds=True).communicate()[0][0]):
if int(read_command('sysctl -n hw.cpu64bit_capable')[0]):
env.Append(CCFLAGS='-arch x86_64')
env.Append(CFLAGS='-arch x86_64')
env.Append(LINKFLAGS='-arch x86_64')
env.Append(ASFLAGS='-arch x86_64')
env['OSX64bit'] = True
except:
pass
@ -425,31 +541,43 @@ if not conf:
# installation used to run scons (and thus this script). If you want
# to link in an alternate version, see above for instructions on how
# to invoke scons with a different copy of the Python interpreter.
from distutils import sysconfig
# Get brief Python version name (e.g., "python2.4") for locating
# include & library files
py_version_name = 'python' + sys.version[:3]
py_getvar = sysconfig.get_config_var
# include path, e.g. /usr/local/include/python2.4
py_header_path = joinpath(sys.exec_prefix, 'include', py_version_name)
env.Append(CPPPATH = py_header_path)
# verify that it works
py_version = 'python' + py_getvar('VERSION')
py_general_include = sysconfig.get_python_inc()
py_platform_include = sysconfig.get_python_inc(plat_specific=True)
py_includes = [ py_general_include ]
if py_platform_include != py_general_include:
py_includes.append(py_platform_include)
py_lib_path = [ py_getvar('LIBDIR') ]
# add the prefix/lib/pythonX.Y/config dir, but only if there is no
# shared library in prefix/lib/.
if not py_getvar('Py_ENABLE_SHARED'):
py_lib_path.append('-L' + py_getvar('LIBPL'))
py_libs = []
for lib in py_getvar('LIBS').split() + py_getvar('SYSLIBS').split():
if lib not in py_libs:
py_libs.append(lib)
py_libs.append('-l' + py_version)
env.Append(CPPPATH=py_includes)
env.Append(LIBPATH=py_lib_path)
# verify that this stuff works
if not conf.CheckHeader('Python.h', '<>'):
print "Error: can't find Python.h header in", py_header_path
print "Error: can't find Python.h header in", py_includes
Exit(1)
# add library path too if it's not in the default place
py_lib_path = None
if sys.exec_prefix != '/usr':
py_lib_path = joinpath(sys.exec_prefix, 'lib')
elif sys.platform == 'cygwin':
# cygwin puts the .dll in /bin for some reason
py_lib_path = '/bin'
if py_lib_path:
env.Append(LIBPATH = py_lib_path)
print 'Adding', py_lib_path, 'to LIBPATH for', py_version_name
if not conf.CheckLib(py_version_name):
print "Error: can't find Python library", py_version_name
for lib in py_libs:
assert lib.startswith('-l')
lib = lib[2:]
if not conf.CheckLib(lib):
print "Error: can't find library %s required by python" % lib
Exit(1)
# On Solaris you need to use libsocket for socket ops
@ -472,13 +600,16 @@ if not have_fenv:
print "Warning: Header file <fenv.h> not found."
print " This host has no IEEE FP rounding mode control."
######################################################################
#
# Check for mysql.
#
mysql_config = WhereIs('mysql_config')
have_mysql = mysql_config != None
have_mysql = bool(mysql_config)
# Check MySQL version.
if have_mysql:
mysql_version = os.popen(mysql_config + ' --version').read()
mysql_version = read_command(mysql_config + ' --version')
min_mysql_version = '4.1'
if compare_versions(mysql_version, min_mysql_version) < 0:
print 'Warning: MySQL', min_mysql_version, 'or newer required.'
@ -495,8 +626,19 @@ if have_mysql:
# This seems to work in all versions
mysql_config_libs = mysql_config + ' --libs'
######################################################################
#
# Finish the configuration
#
env = conf.Finish()
######################################################################
#
# Collect all non-global variables
#
Export('env')
# Define the universe of supported ISAs
all_isa_list = [ ]
Export('all_isa_list')
@ -506,20 +648,20 @@ all_cpu_list = [ ]
default_cpus = [ ]
Export('all_cpu_list', 'default_cpus')
# Sticky options get saved in the options file so they persist from
# Sticky variables get saved in the variables file so they persist from
# one invocation to the next (unless overridden, in which case the new
# value becomes sticky).
sticky_opts = Options(args=ARGUMENTS)
Export('sticky_opts')
sticky_vars = Variables(args=ARGUMENTS)
Export('sticky_vars')
# Non-sticky options only apply to the current build.
nonsticky_opts = Options(args=ARGUMENTS)
Export('nonsticky_opts')
# Non-sticky variables only apply to the current build.
nonsticky_vars = Variables(args=ARGUMENTS)
Export('nonsticky_vars')
# Walk the tree and execute all SConsopts scripts that wil add to the
# above options
for base_dir in base_dir_list:
for root, dirs, files in os.walk(base_dir):
# above variables
for bdir in [ base_dir ] + extras_dir_list:
for root, dirs, files in os.walk(bdir):
if 'SConsopts' in files:
print "Reading", joinpath(root, 'SConsopts')
SConscript(joinpath(root, 'SConsopts'))
@ -528,47 +670,38 @@ all_isa_list.sort()
all_cpu_list.sort()
default_cpus.sort()
sticky_opts.AddOptions(
EnumOption('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
BoolOption('FULL_SYSTEM', 'Full-system support', False),
# There's a bug in scons 0.96.1 that causes ListOptions with list
# values (more than one value) not to be able to be restored from
# a saved option file. If this causes trouble then upgrade to
# scons 0.96.90 or later.
ListOption('CPU_MODELS', 'CPU models', default_cpus, all_cpu_list),
BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
BoolOption('EFENCE', 'Link with Electric Fence malloc debugger',
sticky_vars.AddVariables(
EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
BoolVariable('FULL_SYSTEM', 'Full-system support', False),
ListVariable('CPU_MODELS', 'CPU models', default_cpus, all_cpu_list),
BoolVariable('NO_FAST_ALLOC', 'Disable fast object allocator', False),
BoolVariable('FAST_ALLOC_DEBUG', 'Enable fast object allocator debugging',
False),
BoolOption('SS_COMPATIBLE_FP',
BoolVariable('FAST_ALLOC_STATS', 'Enable fast object allocator statistics',
False),
BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger',
False),
BoolVariable('SS_COMPATIBLE_FP',
'Make floating-point results compatible with SimpleScalar',
False),
BoolOption('USE_SSE2',
BoolVariable('USE_SSE2',
'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts',
False),
BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
BoolOption('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
BoolOption('USE_CHECKER', 'Use checker for detailed CPU models', False),
BoolOption('BATCH', 'Use batch pool for build and tests', False),
('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
('PYTHONHOME',
'Override the default PYTHONHOME for this system (use with caution)',
'%s:%s' % (sys.prefix, sys.exec_prefix)),
BoolVariable('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
BoolVariable('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
BoolVariable('USE_CHECKER', 'Use checker for detailed CPU models', False),
BoolVariable('CP_ANNOTATE', 'Enable critical path annotation capability', False),
)
nonsticky_opts.AddOptions(
BoolOption('update_ref', 'Update test reference outputs', False)
nonsticky_vars.AddVariables(
BoolVariable('update_ref', 'Update test reference outputs', False)
)
# These options get exported to #defines in config/*.hh (see src/SConscript).
env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
'USE_CHECKER', 'PYTHONHOME', 'TARGET_ISA']
# Define a handy 'no-op' action
def no_action(target, source, env):
return 0
env.NoAction = Action(no_action, None)
# These variables get exported to #defines in config/*.hh (see src/SConscript).
env.ExportVariables = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
'USE_MYSQL', 'NO_FAST_ALLOC', 'FAST_ALLOC_DEBUG', \
'FAST_ALLOC_STATS', 'SS_COMPATIBLE_FP', \
'USE_CHECKER', 'TARGET_ISA', 'CP_ANNOTATE']
###################################################
#
@ -577,20 +710,20 @@ env.NoAction = Action(no_action, None)
###################################################
# This function generates a config header file that #defines the
# option symbol to the current option setting (0 or 1). The source
# operands are the name of the option and a Value node containing the
# value of the option.
# 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
# value of the variable.
def build_config_file(target, source, env):
(option, value) = [s.get_contents() for s in source]
(variable, value) = [s.get_contents() for s in source]
f = file(str(target[0]), 'w')
print >> f, '#define', option, value
print >> f, '#define', variable, value
f.close()
return None
# Generate the message to be printed when building the config file.
def build_config_file_string(target, source, env):
(option, value) = [s.get_contents() for s in source]
return "Defining %s as %s in %s." % (option, value, target[0])
(variable, value) = [s.get_contents() for s in source]
return "Defining %s as %s in %s." % (variable, value, target[0])
# Combine the two functions into a scons Action object.
config_action = Action(build_config_file, build_config_file_string)
@ -598,54 +731,31 @@ config_action = Action(build_config_file, build_config_file_string)
# The emitter munges the source & target node lists to reflect what
# we're really doing.
def config_emitter(target, source, env):
# extract option name from Builder arg
option = str(target[0])
# extract variable name from Builder arg
variable = str(target[0])
# True target is config header file
target = joinpath('config', option.lower() + '.hh')
val = env[option]
target = joinpath('config', variable.lower() + '.hh')
val = env[variable]
if isinstance(val, bool):
# Force value to 0/1
val = int(val)
elif isinstance(val, str):
val = '"' + val + '"'
# Sources are option name & value (packaged in SCons Value nodes)
return ([target], [Value(option), Value(val)])
# Sources are variable name & value (packaged in SCons Value nodes)
return ([target], [Value(variable), Value(val)])
config_builder = Builder(emitter = config_emitter, action = config_action)
env.Append(BUILDERS = { 'ConfigFile' : config_builder })
###################################################
#
# Define a SCons builder for copying files. This is used by the
# Python zipfile code in src/python/SConscript, but is placed up here
# since it's potentially more generally applicable.
#
###################################################
copy_builder = Builder(action = Copy("$TARGET", "$SOURCE"))
env.Append(BUILDERS = { 'CopyFile' : copy_builder })
###################################################
#
# Define a simple SCons builder to concatenate files.
#
# Used to append the Python zip archive to the executable.
#
###################################################
concat_builder = Builder(action = Action(['cat $SOURCES > $TARGET',
'chmod +x $TARGET']))
env.Append(BUILDERS = { 'Concat' : concat_builder })
# libelf build is shared across all configs in the build root.
env.SConscript('ext/libelf/SConscript',
build_dir = joinpath(build_root, 'libelf'),
exports = 'env')
variant_dir = joinpath(build_root, 'libelf'))
# gzstream build is shared across all configs in the build root.
env.SConscript('ext/gzstream/SConscript',
variant_dir = joinpath(build_root, 'gzstream'))
###################################################
#
@ -654,19 +764,19 @@ env.SConscript('ext/libelf/SConscript',
###################################################
env['ALL_ISA_LIST'] = all_isa_list
def make_switching_dir(dirname, switch_headers, env):
def make_switching_dir(dname, switch_headers, env):
# Generate the header. target[0] is the full path of the output
# header to generate. 'source' is a dummy variable, since we get the
# list of ISAs from env['ALL_ISA_LIST'].
def gen_switch_hdr(target, source, env):
fname = str(target[0])
basename = os.path.basename(fname)
bname = basename(fname)
f = open(fname, 'w')
f.write('#include "arch/isa_specific.hh"\n')
cond = '#if'
for isa in all_isa_list:
f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n'
% (cond, isa.upper(), dirname, isa, basename))
% (cond, isa.upper(), dname, isa, bname))
cond = '#elif'
f.write('#else\n#error "THE_ISA not set"\n#endif\n')
f.close()
@ -696,66 +806,66 @@ Export('make_switching_dir')
# rename base env
base_env = env
for build_path in build_paths:
print "Building in", build_path
for variant_path in variant_paths:
print "Building in", variant_path
# Make a copy of the build-root environment to use for this config.
env = base_env.Copy()
env['BUILDDIR'] = build_path
env = base_env.Clone()
env['BUILDDIR'] = variant_path
# build_dir is the tail component of build path, and is used to
# variant_dir is the tail component of build path, and is used to
# determine the build parameters (e.g., 'ALPHA_SE')
(build_root, build_dir) = os.path.split(build_path)
(build_root, variant_dir) = splitpath(variant_path)
# Set env options according to the build directory config.
sticky_opts.files = []
# Options for $BUILD_ROOT/$BUILD_DIR are stored in
# $BUILD_ROOT/options/$BUILD_DIR so you can nuke
# $BUILD_ROOT/$BUILD_DIR without losing your options settings.
current_opts_file = joinpath(build_root, 'options', build_dir)
if isfile(current_opts_file):
sticky_opts.files.append(current_opts_file)
print "Using saved options file %s" % current_opts_file
# Set env variables according to the build directory config.
sticky_vars.files = []
# Variables for $BUILD_ROOT/$VARIANT_DIR are stored in
# $BUILD_ROOT/variables/$VARIANT_DIR so you can nuke
# $BUILD_ROOT/$VARIANT_DIR without losing your variables settings.
current_vars_file = joinpath(build_root, 'variables', variant_dir)
if isfile(current_vars_file):
sticky_vars.files.append(current_vars_file)
print "Using saved variables file %s" % current_vars_file
else:
# Build dir-specific options file doesn't exist.
# Build dir-specific variables file doesn't exist.
# Make sure the directory is there so we can create it later
opt_dir = os.path.dirname(current_opts_file)
opt_dir = dirname(current_vars_file)
if not isdir(opt_dir):
os.mkdir(opt_dir)
mkdir(opt_dir)
# Get default build options from source tree. Options are
# normally determined by name of $BUILD_DIR, but can be
# Get default build variables from source tree. Variables are
# normally determined by name of $VARIANT_DIR, but can be
# overriden by 'default=' arg on command line.
default_opts_file = joinpath('build_opts',
ARGUMENTS.get('default', build_dir))
if isfile(default_opts_file):
sticky_opts.files.append(default_opts_file)
print "Options file %s not found,\n using defaults in %s" \
% (current_opts_file, default_opts_file)
default_vars_file = joinpath('build_opts',
ARGUMENTS.get('default', variant_dir))
if isfile(default_vars_file):
sticky_vars.files.append(default_vars_file)
print "Variables file %s not found,\n using defaults in %s" \
% (current_vars_file, default_vars_file)
else:
print "Error: cannot find options file %s or %s" \
% (current_opts_file, default_opts_file)
print "Error: cannot find variables file %s or %s" \
% (current_vars_file, default_vars_file)
Exit(1)
# Apply current option settings to env
sticky_opts.Update(env)
nonsticky_opts.Update(env)
# Apply current variable settings to env
sticky_vars.Update(env)
nonsticky_vars.Update(env)
help_text += "\nSticky options for %s:\n" % build_dir \
+ sticky_opts.GenerateHelpText(env) \
+ "\nNon-sticky options for %s:\n" % build_dir \
+ nonsticky_opts.GenerateHelpText(env)
help_text += "\nSticky variables for %s:\n" % variant_dir \
+ sticky_vars.GenerateHelpText(env) \
+ "\nNon-sticky variables for %s:\n" % variant_dir \
+ nonsticky_vars.GenerateHelpText(env)
# Process option settings.
# Process variable settings.
if not have_fenv and env['USE_FENV']:
print "Warning: <fenv.h> not available; " \
"forcing USE_FENV to False in", build_dir + "."
"forcing USE_FENV to False in", variant_dir + "."
env['USE_FENV'] = False
if not env['USE_FENV']:
print "Warning: No IEEE FP rounding mode control in", build_dir + "."
print "Warning: No IEEE FP rounding mode control in", variant_dir + "."
print " FP results may deviate slightly from other platforms."
if env['EFENCE']:
@ -764,44 +874,29 @@ for build_path in build_paths:
if env['USE_MYSQL']:
if not have_mysql:
print "Warning: MySQL not available; " \
"forcing USE_MYSQL to False in", build_dir + "."
"forcing USE_MYSQL to False in", variant_dir + "."
env['USE_MYSQL'] = False
else:
print "Compiling in", build_dir, "with MySQL support."
print "Compiling in", variant_dir, "with MySQL support."
env.ParseConfig(mysql_config_libs)
env.ParseConfig(mysql_config_include)
# Save sticky option settings back to current options file
sticky_opts.Save(current_opts_file, env)
# Do this after we save setting back, or else we'll tack on an
# extra 'qdo' every time we run scons.
if env['BATCH']:
env['CC'] = env['BATCH_CMD'] + ' ' + env['CC']
env['CXX'] = env['BATCH_CMD'] + ' ' + env['CXX']
# Save sticky variable settings back to current variables file
sticky_vars.Save(current_vars_file, env)
if env['USE_SSE2']:
env.Append(CCFLAGS='-msse2')
# The src/SConscript file sets up the build rules in 'env' according
# to the configured options. It returns a list of environments,
# to the configured variables. It returns a list of environments,
# one for each variant build (debug, opt, etc.)
envList = SConscript('src/SConscript', build_dir = build_path,
envList = SConscript('src/SConscript', variant_dir = variant_path,
exports = 'env')
# Set up the regression tests for each build.
for e in envList:
SConscript('tests/SConscript',
build_dir = joinpath(build_path, 'tests', e.Label),
variant_dir = joinpath(variant_path, 'tests', e.Label),
exports = { 'env' : e }, duplicate = False)
Help(help_text)
###################################################
#
# Let SCons do its thing. At this point SCons will use the defined
# build environments to build the requested targets.
#
###################################################

View file

@ -68,7 +68,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
read_only = True))
self.intrctrl = IntrControl()
self.mem_mode = mem_mode
self.sim_console = SimConsole()
self.terminal = Terminal()
self.kernel = binary('vmlinux')
self.pal = binary('ts_osfpal')
self.console = binary('console')
@ -148,7 +148,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None):
read_only = True))
self.intrctrl = IntrControl()
self.mem_mode = mem_mode
self.sim_console = SimConsole()
self.terminal = Terminal()
self.kernel = binary('mips/vmlinux')
self.console = binary('mips/console')
self.boot_osflags = 'root=/dev/hda1 console=ttyS0'
@ -159,11 +159,14 @@ def x86IOAddress(port):
IO_address_space_base = 0x8000000000000000
return IO_address_space_base + port;
def makeLinuxX86System(mem_mode, mdesc = None):
self = LinuxX86System()
def makeX86System(mem_mode, mdesc = None, self = None):
if self == None:
self = X86System()
if not mdesc:
# generic system
mdesc = SysConfig()
mdesc.diskname = 'x86root.img'
self.readfile = mdesc.script()
# Physical memory
@ -177,22 +180,168 @@ def makeLinuxX86System(mem_mode, mdesc = None):
self.bridge.side_a = self.iobus.port
self.bridge.side_b = self.membus.port
# Serial port and console
self.console = SimConsole()
self.com_1 = Uart8250()
self.com_1.pio_addr = x86IOAddress(0x3f8)
self.com_1.pio = self.iobus.port
self.com_1.sim_console = self.console
# Command line
self.boot_osflags = 'earlyprintk=ttyS0'
# Platform
self.opteron = Opteron()
self.opteron.attachIO(self.iobus)
self.pc = Pc()
self.pc.attachIO(self.iobus)
self.intrctrl = IntrControl()
# Disks
disk0 = CowIdeDisk(driveID='master')
disk2 = CowIdeDisk(driveID='master')
disk0.childImage(mdesc.disk())
disk2.childImage(disk('linux-bigswap2.img'))
self.pc.south_bridge.ide.disks = [disk0, disk2]
# Add in a Bios information structure.
structures = [X86SMBiosBiosInformation()]
self.smbios_table.structures = structures
# Set up the Intel MP table
bp = X86IntelMPProcessor(
local_apic_id = 0,
local_apic_version = 0x14,
enable = True,
bootstrap = True)
self.intel_mp_table.add_entry(bp)
io_apic = X86IntelMPIOAPIC(
id = 1,
version = 0x11,
enable = True,
address = 0xfec00000)
self.intel_mp_table.add_entry(io_apic)
isa_bus = X86IntelMPBus(bus_id = 0, bus_type='ISA')
self.intel_mp_table.add_entry(isa_bus)
pci_bus = X86IntelMPBus(bus_id = 1, bus_type='PCI')
self.intel_mp_table.add_entry(pci_bus)
connect_busses = X86IntelMPBusHierarchy(bus_id=0,
subtractive_decode=True, parent_bus=1)
self.intel_mp_table.add_entry(connect_busses)
pci_dev4_inta = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 1,
source_bus_irq = 0 + (4 << 2),
dest_io_apic_id = 1,
dest_io_apic_intin = 16)
assign_8259_0_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 0,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_0_to_apic)
assign_0_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 0,
dest_io_apic_id = 1,
dest_io_apic_intin = 2)
self.intel_mp_table.add_entry(assign_0_to_apic)
assign_8259_1_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 1,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_1_to_apic)
assign_1_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 1,
dest_io_apic_id = 1,
dest_io_apic_intin = 1)
self.intel_mp_table.add_entry(assign_1_to_apic)
assign_8259_4_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 4,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_4_to_apic)
assign_4_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 4,
dest_io_apic_id = 1,
dest_io_apic_intin = 4)
self.intel_mp_table.add_entry(assign_4_to_apic)
assign_8259_12_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 12,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_12_to_apic)
assign_12_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 12,
dest_io_apic_id = 1,
dest_io_apic_intin = 12)
self.intel_mp_table.add_entry(assign_12_to_apic)
assign_8259_14_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'ExtInt',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 14,
dest_io_apic_id = 1,
dest_io_apic_intin = 0)
self.intel_mp_table.add_entry(assign_8259_14_to_apic)
assign_14_to_apic = X86IntelMPIOIntAssignment(
interrupt_type = 'INT',
polarity = 'ConformPolarity',
trigger = 'ConformTrigger',
source_bus_id = 0,
source_bus_irq = 14,
dest_io_apic_id = 1,
dest_io_apic_intin = 14)
self.intel_mp_table.add_entry(assign_14_to_apic)
def makeLinuxX86System(mem_mode, mdesc = None):
self = LinuxX86System()
# Build up a generic x86 system and then specialize it for Linux
makeX86System(mem_mode, mdesc, self)
# We assume below that there's at least 1MB of memory. We'll require 2
# just to avoid corner cases.
assert(self.physmem.range.second >= 0x200000)
# Mark the first megabyte of memory as reserved
self.e820_table.entries.append(X86E820Entry(
addr = 0,
size = '1MB',
range_type = 2))
# Mark the rest as available
self.e820_table.entries.append(X86E820Entry(
addr = 0x100000,
size = '%dB' % (self.physmem.range.second - 0x100000 - 1),
range_type = 1))
# Command line
self.boot_osflags = 'earlyprintk=ttyS0 console=ttyS0 lpj=7999923 ' + \
'root=/dev/hda1'
return self

View file

@ -29,6 +29,7 @@
# system options
parser.add_option("-d", "--detailed", action="store_true")
parser.add_option("-t", "--timing", action="store_true")
parser.add_option("--inorder", action="store_true")
parser.add_option("-n", "--num-cpus", type="int", default=1)
parser.add_option("--caches", action="store_true")
parser.add_option("--l2cache", action="store_true")

View file

@ -43,6 +43,11 @@ def setCPUClass(options):
print "O3 CPU must be used with caches"
sys.exit(1)
class TmpClass(DerivO3CPU): pass
elif options.inorder:
if not options.caches:
print "InOrder CPU must be used with caches"
sys.exit(1)
class TmpClass(InOrderCPU): pass
else:
class TmpClass(AtomicSimpleCPU): pass
atomic = True
@ -78,10 +83,10 @@ def run(options, root, testsys, cpu_class):
cptdir = getcwd()
if options.fast_forward and options.checkpoint_restore != None:
m5.panic("Error: Can't specify both --fast-forward and --checkpoint-restore")
m5.fatal("Error: Can't specify both --fast-forward and --checkpoint-restore")
if options.standard_switch and not options.caches:
m5.panic("Error: Must specify --caches when using --standard-switch")
m5.fatal("Error: Must specify --caches when using --standard-switch")
np = options.num_cpus
max_checkpoints = options.max_checkpoints
@ -128,8 +133,8 @@ def run(options, root, testsys, cpu_class):
testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
# Fast forward to a simpoint (warning: time consuming)
elif options.simpoint:
if testsys.cpu[i].workload[0].simpoint == None:
m5.panic('simpoint not found')
if testsys.cpu[i].workload[0].simpoint == 0:
m5.fatal('simpoint not found')
testsys.cpu[i].max_insts_any_thread = \
testsys.cpu[i].workload[0].simpoint
# No distance specified, just switch
@ -162,8 +167,8 @@ def run(options, root, testsys, cpu_class):
# Set an instruction break point
if options.simpoint:
for i in xrange(np):
if testsys.cpu[i].workload[0].simpoint == None:
m5.panic('no simpoint for testsys.cpu[%d].workload[0]' % i)
if testsys.cpu[i].workload[0].simpoint == 0:
m5.fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
testsys.cpu[i].max_insts_any_thread = checkpoint_inst
# used for output below
@ -183,13 +188,13 @@ def run(options, root, testsys, cpu_class):
import re
if not isdir(cptdir):
m5.panic("checkpoint dir %s does not exist!" % cptdir)
m5.fatal("checkpoint dir %s does not exist!", cptdir)
if options.at_instruction:
checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \
(options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir):
m5.panic("Unable to find checkpoint directory %s" % \
m5.fatal("Unable to find checkpoint directory %s",
checkpoint_dir)
print "Restoring checkpoint ..."
@ -197,8 +202,8 @@ def run(options, root, testsys, cpu_class):
print "Done."
elif options.simpoint:
# assume workload 0 has the simpoint
if testsys.cpu[0].workload[0].simpoint == None:
m5.panic('Unable to find simpoint')
if testsys.cpu[0].workload[0].simpoint == 0:
m5.fatal('Unable to find simpoint')
options.checkpoint_restore += \
int(testsys.cpu[0].workload[0].simpoint)
@ -206,8 +211,8 @@ def run(options, root, testsys, cpu_class):
checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \
(options.bench, options.checkpoint_restore))
if not exists(checkpoint_dir):
m5.panic("Unable to find checkpoint directory %s.%s" % \
(options.bench, options.checkpoint_restore))
m5.fatal("Unable to find checkpoint directory %s.%s",
options.bench, options.checkpoint_restore)
print "Restoring checkpoint ..."
m5.restoreCheckpoint(root,checkpoint_dir)
@ -226,7 +231,7 @@ def run(options, root, testsys, cpu_class):
cpt_num = options.checkpoint_restore
if cpt_num > len(cpts):
m5.panic('Checkpoint %d not found' % cpt_num)
m5.fatal('Checkpoint %d not found', cpt_num)
## Adjust max tick based on our starting tick
maxtick = maxtick - int(cpts[cpt_num - 1])

View file

@ -140,6 +140,7 @@ class Benchmark(object):
process_args['input'] = self.stdin
if self.stdout:
process_args['output'] = self.stdout
if self.simpoint:
process_args['simpoint'] = self.simpoint
# explicit keywords override defaults
process_args.update(kwargs)

View file

@ -29,6 +29,10 @@
import optparse, os, sys
import m5
if not m5.build_env['FULL_SYSTEM']:
m5.fatal("This script requires full-system mode (*_FS).")
from m5.objects import *
m5.AddToPath('../common')
from FSConfig import *
@ -37,9 +41,6 @@ from Benchmarks import *
import Simulation
from Caches import *
if not m5.build_env['FULL_SYSTEM']:
m5.panic("This script requires full-system mode (ALPHA_FS).")
# Get paths we might need. It's expected this file is in m5/configs/example.
config_path = os.path.dirname(os.path.abspath(__file__))
config_root = os.path.dirname(config_path)
@ -104,7 +105,7 @@ elif m5.build_env['TARGET_ISA'] == "sparc":
elif m5.build_env['TARGET_ISA'] == "x86":
test_sys = makeLinuxX86System(test_mem_mode, bm[0])
else:
m5.panic("incapable of building non-alpha or non-sparc full system!")
m5.fatal("incapable of building non-alpha or non-sparc full system!")
if options.kernel is not None:
test_sys.kernel = binary(options.kernel)

View file

@ -31,8 +31,13 @@
# "m5 test.py"
import m5
if m5.build_env['FULL_SYSTEM']:
m5.fatal("This script requires syscall emulation mode (*_SE).")
from m5.objects import *
import os, optparse, sys
from os.path import join as joinpath
m5.AddToPath('../common')
import Simulation
from Caches import *
@ -47,13 +52,13 @@ parser = optparse.OptionParser()
# Benchmark options
parser.add_option("-c", "--cmd",
default=os.path.join(m5_root, "tests/test-progs/hello/bin/alpha/linux/hello"),
default=joinpath(m5_root, "tests/test-progs/hello/bin/alpha/linux/hello"),
help="The binary to run in syscall emulation mode.")
parser.add_option("-o", "--options", default="",
help="The options to pass to the binary, use \" \" around the entire\
string.")
parser.add_option("-i", "--input", default="",
help="A file of input to give to the binary.")
help='The options to pass to the binary, use " " around the entire string')
parser.add_option("-i", "--input", default="", help="Read stdin from a file.")
parser.add_option("--output", default="", help="Redirect stdout to a file.")
parser.add_option("--errout", default="", help="Redirect stderr to a file.")
execfile(os.path.join(config_root, "common", "Options.py"))
@ -81,6 +86,10 @@ else:
if options.input != "":
process.input = options.input
if options.output != "":
process.output = options.output
if options.errout != "":
process.errout = options.errout
if options.detailed:
#check for SMT workload
@ -89,9 +98,15 @@ if options.detailed:
process = []
smt_idx = 0
inputs = []
outputs = []
errouts = []
if options.input != "":
inputs = options.input.split(';')
if options.output != "":
outputs = options.output.split(';')
if options.errout != "":
errouts = options.errout.split(';')
for wrkld in workloads:
smt_process = LiveProcess()
@ -99,6 +114,10 @@ if options.detailed:
smt_process.cmd = wrkld + " " + options.options
if inputs and inputs[smt_idx]:
smt_process.input = inputs[smt_idx]
if outputs and outputs[smt_idx]:
smt_process.output = outputs[smt_idx]
if errouts and errouts[smt_idx]:
smt_process.errout = errouts[smt_idx]
process += [smt_process, ]
smt_idx += 1

504
ext/gzstream/LICENSE Normal file
View file

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

38
ext/gzstream/SConscript Normal file
View file

@ -0,0 +1,38 @@
# -*- mode:python -*-
# Copyright (c) 2004-2005 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Nathan Binkert
Import('env')
env.Library('gzstream', [File('gzstream.cc')])
env.Append(CPPPATH=Dir('.'))
env.Append(LIBS=['gzstream'])
env.Append(LIBPATH=[Dir('.')])

1
ext/gzstream/VERSION Normal file
View file

@ -0,0 +1 @@
1.5 (08 Jan 2003)

165
ext/gzstream/gzstream.cc Normal file
View file

@ -0,0 +1,165 @@
// ============================================================================
// gzstream, C++ iostream classes wrapping the zlib compression library.
// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ============================================================================
//
// File : gzstream.C
// Revision : $Revision: 1.7 $
// Revision_date : $Date: 2003/01/08 14:41:27 $
// Author(s) : Deepak Bandyopadhyay, Lutz Kettner
//
// Standard streambuf implementation following Nicolai Josuttis, "The
// Standard C++ Library".
// ============================================================================
#include <gzstream.hh>
#include <iostream>
#include <string.h> // for memcpy
#ifdef GZSTREAM_NAMESPACE
namespace GZSTREAM_NAMESPACE {
#endif
// ----------------------------------------------------------------------------
// Internal classes to implement gzstream. See header file for user classes.
// ----------------------------------------------------------------------------
// --------------------------------------
// class gzstreambuf:
// --------------------------------------
gzstreambuf* gzstreambuf::open( const char* name, int open_mode) {
if ( is_open())
return (gzstreambuf*)0;
mode = open_mode;
// no append nor read/write mode
if ((mode & std::ios::ate) || (mode & std::ios::app)
|| ((mode & std::ios::in) && (mode & std::ios::out)))
return (gzstreambuf*)0;
char fmode[10];
char* fmodeptr = fmode;
if ( mode & std::ios::in)
*fmodeptr++ = 'r';
else if ( mode & std::ios::out)
*fmodeptr++ = 'w';
*fmodeptr++ = 'b';
*fmodeptr = '\0';
file = gzopen( name, fmode);
if (file == 0)
return (gzstreambuf*)0;
opened = 1;
return this;
}
gzstreambuf * gzstreambuf::close() {
if ( is_open()) {
sync();
opened = 0;
if ( gzclose( file) == Z_OK)
return this;
}
return (gzstreambuf*)0;
}
int gzstreambuf::underflow() { // used for input buffer only
if ( gptr() && ( gptr() < egptr()))
return * reinterpret_cast<unsigned char *>( gptr());
if ( ! (mode & std::ios::in) || ! opened)
return EOF;
// Josuttis' implementation of inbuf
int n_putback = gptr() - eback();
if ( n_putback > 4)
n_putback = 4;
memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
int num = gzread( file, buffer+4, bufferSize-4);
if (num <= 0) // ERROR or EOF
return EOF;
// reset buffer pointers
setg( buffer + (4 - n_putback), // beginning of putback area
buffer + 4, // read position
buffer + 4 + num); // end of buffer
// return next character
return *reinterpret_cast<unsigned char *>(gptr());
}
int gzstreambuf::flush_buffer() {
// Separate the writing of the buffer from overflow() and
// sync() operation.
int w = pptr() - pbase();
if ( gzwrite( file, pbase(), w) != w)
return EOF;
pbump( -w);
return w;
}
int gzstreambuf::overflow( int c) { // used for output buffer only
if ( ! ( mode & std::ios::out) || ! opened)
return EOF;
if (c != EOF) {
*pptr() = c;
pbump(1);
}
if ( flush_buffer() == EOF)
return EOF;
return c;
}
int gzstreambuf::sync() {
// Changed to use flush_buffer() instead of overflow( EOF)
// which caused improper behavior with std::endl and flush(),
// bug reported by Vincent Ricard.
if ( pptr() && pptr() > pbase()) {
if ( flush_buffer() == EOF)
return -1;
}
return 0;
}
// --------------------------------------
// class gzstreambase:
// --------------------------------------
gzstreambase::gzstreambase( const char* name, int mode) {
init( &buf);
open( name, mode);
}
gzstreambase::~gzstreambase() {
buf.close();
}
void gzstreambase::open( const char* name, int open_mode) {
if ( ! buf.open( name, open_mode))
clear( rdstate() | std::ios::badbit);
}
void gzstreambase::close() {
if ( buf.is_open())
if ( ! buf.close())
clear( rdstate() | std::ios::badbit);
}
#ifdef GZSTREAM_NAMESPACE
} // namespace GZSTREAM_NAMESPACE
#endif
// ============================================================================
// EOF //

122
ext/gzstream/gzstream.hh Normal file
View file

@ -0,0 +1,122 @@
// ============================================================================
// gzstream, C++ iostream classes wrapping the zlib compression library.
// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ============================================================================
//
// File : gzstream.h
// Revision : $Revision: 1.5 $
// Revision_date : $Date: 2002/04/26 23:30:15 $
// Author(s) : Deepak Bandyopadhyay, Lutz Kettner
//
// Standard streambuf implementation following Nicolai Josuttis, "The
// Standard C++ Library".
// ============================================================================
#ifndef GZSTREAM_H
#define GZSTREAM_H 1
// standard C++ with new header file names and std:: namespace
#include <iostream>
#include <fstream>
#include <zlib.h>
#ifdef GZSTREAM_NAMESPACE
namespace GZSTREAM_NAMESPACE {
#endif
// ----------------------------------------------------------------------------
// Internal classes to implement gzstream. See below for user classes.
// ----------------------------------------------------------------------------
class gzstreambuf : public std::streambuf {
private:
static const int bufferSize = 47+256; // size of data buff
// totals 512 bytes under g++ for igzstream at the end.
gzFile file; // file handle for compressed file
char buffer[bufferSize]; // data buffer
char opened; // open/close state of stream
int mode; // I/O mode
int flush_buffer();
public:
gzstreambuf() : opened(0) {
setp( buffer, buffer + (bufferSize-1));
setg( buffer + 4, // beginning of putback area
buffer + 4, // read position
buffer + 4); // end position
// ASSERT: both input & output capabilities will not be used together
}
int is_open() { return opened; }
gzstreambuf* open( const char* name, int open_mode);
gzstreambuf* close();
~gzstreambuf() { close(); }
virtual int overflow( int c = EOF);
virtual int underflow();
virtual int sync();
};
class gzstreambase : virtual public std::ios {
protected:
gzstreambuf buf;
public:
gzstreambase() { init(&buf); }
gzstreambase( const char* name, int open_mode);
~gzstreambase();
int is_open() { return buf.is_open(); }
void open( const char* name, int open_mode);
void close();
gzstreambuf* rdbuf() { return &buf; }
};
// ----------------------------------------------------------------------------
// User classes. Use igzstream and ogzstream analogously to ifstream and
// ofstream respectively. They read and write files based on the gz*
// function interface of the zlib. Files are compatible with gzip compression.
// ----------------------------------------------------------------------------
class igzstream : public gzstreambase, public std::istream {
public:
igzstream() : std::istream( &buf) {}
igzstream( const char* name, int open_mode = std::ios::in)
: gzstreambase( name, open_mode | std::ios::in), std::istream( &buf) {}
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
void open( const char* name, int open_mode = std::ios::in) {
gzstreambase::open( name, open_mode);
}
};
class ogzstream : public gzstreambase, public std::ostream {
public:
ogzstream() : std::ostream( &buf) {}
ogzstream( const char* name, int mode = std::ios::out)
: gzstreambase( name, mode | std::ios::out), std::ostream( &buf) {}
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
void open( const char* name, int open_mode = std::ios::out) {
gzstreambase::open( name, open_mode);
}
};
#ifdef GZSTREAM_NAMESPACE
} // namespace GZSTREAM_NAMESPACE
#endif
#endif // GZSTREAM_H
// ============================================================================
// EOF //

View file

@ -87,16 +87,13 @@ ElfFile('libelf_convert.c')
ElfFile('libelf_fsize.c')
ElfFile('libelf_msize.c')
m4env = Environment(ENV=os.environ)
if env.get('CC'):
m4env['CC'] = env['CC']
if env.get('CXX'):
m4env['CXX'] = env['CXX']
if env.get('OSX64bit'):
m4env.Append(CFLAGS='-arch x86_64')
m4env.Append(LINKFLAGS='-arch x86_64')
m4env = env.Clone()
if env['GCC']:
major,minor,dot = [ int(x) for x in env['CXXVERSION'].split('.')]
if major >= 4:
m4env.Append(CCFLAGS=['-Wno-pointer-sign'])
m4env.Append(CCFLAGS=['-Wno-implicit'])
del m4env['CPPPATH']
# If we have gm4 use it
if m4env.Detect('gm4'):
@ -117,7 +114,10 @@ m4env.M4(target=File('libelf_fsize.c'),
source=[File('elf_types.m4'), File('libelf_fsize.m4')])
m4env.M4(target=File('libelf_msize.c'),
source=[File('elf_types.m4'), File('libelf_msize.m4')])
m4env.Library('elf', elf_files)
# Build libelf as a static library with PIC code so it can be linked
# into either m5 or the library
m4env.Library('elf', [m4env.SharedObject(f) for f in elf_files])
env.Append(CPPPATH=Dir('.'))
env.Append(LIBS=['elf'])

View file

@ -28,11 +28,15 @@
#
# Authors: Nathan Binkert
import array
import imp
import marshal
import os
import re
import sys
import zlib
from os.path import basename, exists, isdir, isfile, join as joinpath
from os.path import basename, dirname, exists, isdir, isfile, join as joinpath
import SCons
@ -44,6 +48,8 @@ Import('*')
# Children need to see the environment
Export('env')
build_env = dict([(opt, env[opt]) for opt in env.ExportVariables])
def sort_list(_list):
"""return a sorted copy of '_list'"""
if isinstance(_list, list):
@ -54,39 +60,60 @@ def sort_list(_list):
return _list
class PySourceFile(object):
def __init__(self, package, source):
filename = str(source)
invalid_sym_char = re.compile('[^A-z0-9_]')
def __init__(self, package, tnode):
snode = tnode.srcnode()
filename = str(tnode)
pyname = basename(filename)
assert pyname.endswith('.py')
name = pyname[:-3]
if package:
path = package.split('.')
modpath = path
else:
path = []
modpath = path[:]
if name != '__init__':
modpath += [name]
modpath = '.'.join(modpath)
arcpath = package.split('.') + [ pyname + 'c' ]
arcpath = path + [ pyname ]
arcname = joinpath(*arcpath)
self.source = source
debugname = snode.abspath
if not exists(debugname):
debugname = tnode.abspath
self.tnode = tnode
self.snode = snode
self.pyname = pyname
self.srcpath = source.srcnode().abspath
self.package = package
self.modpath = modpath
self.arcname = arcname
self.filename = filename
self.debugname = debugname
self.compiled = File(filename + 'c')
self.assembly = File(filename + '.s')
self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath)
########################################################################
# Code for adding source files of various types
#
cc_sources = []
cc_lib_sources = []
def Source(source):
'''Add a C/C++ source file to the build'''
'''Add a source file to the libm5 build'''
if not isinstance(source, SCons.Node.FS.File):
source = File(source)
cc_sources.append(source)
cc_lib_sources.append(source)
cc_bin_sources = []
def BinSource(source):
'''Add a source file to the m5 binary build'''
if not isinstance(source, SCons.Node.FS.File):
source = File(source)
cc_bin_sources.append(source)
py_sources = []
def PySource(package, source):
@ -123,40 +150,50 @@ def SwigSource(package, source):
val = source,package
swig_sources.append(val)
unit_tests = []
def UnitTest(target, sources):
if not isinstance(sources, (list, tuple)):
sources = [ sources ]
srcs = []
for source in sources:
if not isinstance(source, SCons.Node.FS.File):
source = File(source)
srcs.append(source)
unit_tests.append((target, srcs))
# Children should have access
Export('Source')
Export('BinSource')
Export('PySource')
Export('SimObject')
Export('SwigSource')
Export('UnitTest')
########################################################################
#
# Trace Flags
#
all_flags = {}
trace_flags = []
def TraceFlag(name, desc=''):
if name in all_flags:
trace_flags = {}
def TraceFlag(name, desc=None):
if name in trace_flags:
raise AttributeError, "Flag %s already specified" % name
flag = (name, (), desc)
trace_flags.append(flag)
all_flags[name] = ()
trace_flags[name] = (name, (), desc)
def CompoundFlag(name, flags, desc=''):
if name in all_flags:
def CompoundFlag(name, flags, desc=None):
if name in trace_flags:
raise AttributeError, "Flag %s already specified" % name
compound = tuple(flags)
for flag in compound:
if flag not in all_flags:
if flag not in trace_flags:
raise AttributeError, "Trace flag %s not found" % flag
if all_flags[flag]:
if trace_flags[flag][1]:
raise AttributeError, \
"Compound flag can't point to another compound flag"
flag = (name, compound, desc)
trace_flags.append(flag)
all_flags[name] = compound
trace_flags[name] = (name, compound, desc)
Export('TraceFlag')
Export('CompoundFlag')
@ -172,15 +209,22 @@ Export('CompoundFlag')
# files.
env.Append(CPPPATH=Dir('.'))
for extra_dir in extras_dir_list:
env.Append(CPPPATH=Dir(extra_dir))
# Add a flag defining what THE_ISA should be for all compilation
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
# Workaround for bug in SCons version > 0.97d20071212
# Scons bug id: 2006 M5 Bug id: 308
for root, dirs, files in os.walk(base_dir, topdown=True):
Dir(root[len(base_dir) + 1:])
########################################################################
#
# Walk the tree and execute all SConscripts in subdirectories
#
for base_dir in base_dir_list:
here = Dir('.').srcnode().abspath
for root, dirs, files in os.walk(base_dir, topdown=True):
if root == here:
@ -191,7 +235,14 @@ for base_dir in base_dir_list:
build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
SConscript(joinpath(root, 'SConscript'), build_dir=build_dir)
for opt in env.ExportOptions:
for extra_dir in extras_dir_list:
prefix_len = len(dirname(extra_dir)) + 1
for root, dirs, files in os.walk(extra_dir, topdown=True):
if 'SConscript' in files:
build_dir = joinpath(env['BUILDDIR'], root[prefix_len:])
SConscript(joinpath(root, 'SConscript'), build_dir=build_dir)
for opt in env.ExportVariables:
env.ConfigFile(opt)
########################################################################
@ -199,55 +250,150 @@ for opt in env.ExportOptions:
# Prevent any SimObjects from being added after this point, they
# should all have been added in the SConscripts above
#
class DictImporter(object):
'''This importer takes a dictionary of arbitrary module names that
map to arbitrary filenames.'''
def __init__(self, modules):
self.modules = modules
self.installed = set()
def __del__(self):
self.unload()
def unload(self):
import sys
for module in self.installed:
del sys.modules[module]
self.installed = set()
def find_module(self, fullname, path):
if fullname == 'defines':
return self
if fullname == 'm5.objects':
return self
if fullname.startswith('m5.internal'):
return None
if fullname in self.modules and exists(self.modules[fullname]):
return self
return None
def load_module(self, fullname):
mod = imp.new_module(fullname)
sys.modules[fullname] = mod
self.installed.add(fullname)
mod.__loader__ = self
if fullname == 'm5.objects':
mod.__path__ = fullname.split('.')
return mod
if fullname == 'defines':
mod.__dict__['buildEnv'] = build_env
return mod
srcfile = self.modules[fullname]
if basename(srcfile) == '__init__.py':
mod.__path__ = fullname.split('.')
mod.__file__ = srcfile
exec file(srcfile, 'r') in mod.__dict__
return mod
py_modules = {}
for source in py_sources:
py_modules[source.modpath] = source.snode.abspath
# install the python importer so we can grab stuff from the source
# tree itself. We can't have SimObjects added after this point or
# else we won't know about them for the rest of the stuff.
sim_objects_fixed = True
importer = DictImporter(py_modules)
sys.meta_path[0:0] = [ importer ]
########################################################################
#
# Manually turn python/generate.py into a python module and import it
#
generate_file = File('python/generate.py')
generate_module = imp.new_module('generate')
sys.modules['generate'] = generate_module
exec file(generate_file.srcnode().abspath, 'r') in generate_module.__dict__
import m5
########################################################################
#
# build a generate
#
from generate import Generate
optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
generate = Generate(py_sources, sim_object_modfiles, optionDict)
m5 = generate.m5
# import all sim objects so we can populate the all_objects list
# make sure that we're working with a list, then let's sort it
sim_objects = list(sim_object_modfiles)
sim_objects.sort()
for simobj in sim_objects:
exec('from m5.objects import %s' % simobj)
# we need to unload all of the currently imported modules so that they
# will be re-imported the next time the sconscript is run
importer.unload()
sys.meta_path.remove(importer)
sim_objects = m5.SimObject.allClasses
all_enums = m5.params.allEnums
all_params = {}
for name,obj in sim_objects.iteritems():
for param in obj._params.local.values():
if not hasattr(param, 'swig_decl'):
continue
pname = param.ptype_str
if pname not in all_params:
all_params[pname] = param
########################################################################
#
# calculate extra dependencies
#
module_depends = ["m5", "m5.SimObject", "m5.params"]
module_depends = [ File(generate.py_modules[dep]) for dep in module_depends ]
file_depends = [ generate_file ]
depends = module_depends + file_depends
depends = [ File(py_modules[dep]) for dep in module_depends ]
########################################################################
#
# Commands for the basic automatically generated python files
#
# Generate Python file containing a dict specifying the current
# build_env flags.
def makeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
build_env, hg_info = [ x.get_contents() for x in source ]
print >>f, "buildEnv = %s" % build_env
print >>f, "hgRev = '%s'" % hg_info
f.close()
defines_info = [ Value(build_env), Value(env['HG_INFO']) ]
# Generate a file with all of the compile options in it
env.Command('python/m5/defines.py', Value(optionDict),
generate.makeDefinesPyFile)
env.Command('python/m5/defines.py', defines_info, makeDefinesPyFile)
PySource('m5', 'python/m5/defines.py')
# Generate python file containing info about the M5 source code
def makeInfoPyFile(target, source, env):
f = file(str(target[0]), 'w')
for src in source:
data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
print >>f, "%s = %s" % (src, repr(data))
f.close()
# Generate a file that wraps the basic top level files
env.Command('python/m5/info.py',
[ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
generate.makeInfoPyFile)
makeInfoPyFile)
PySource('m5', 'python/m5/info.py')
# Generate the __init__.py file for m5.objects
def makeObjectsInitFile(target, source, env):
f = file(str(target[0]), 'w')
print >>f, 'from params import *'
print >>f, 'from m5.SimObject import *'
for module in source:
print >>f, 'from %s import *' % module.get_contents()
f.close()
# Generate an __init__.py file for the objects package
env.Command('python/m5/objects/__init__.py',
[ Value(o) for o in sort_list(sim_object_modfiles) ],
generate.makeObjectsInitFile)
makeObjectsInitFile)
PySource('m5.objects', 'python/m5/objects/__init__.py')
########################################################################
@ -255,51 +401,189 @@ PySource('m5.objects', 'python/m5/objects/__init__.py')
# Create all of the SimObject param headers and enum headers
#
def createSimObjectParam(target, source, env):
assert len(target) == 1 and len(source) == 1
hh_file = file(target[0].abspath, 'w')
name = str(source[0].get_contents())
obj = sim_objects[name]
print >>hh_file, obj.cxx_decl()
def createSwigParam(target, source, env):
assert len(target) == 1 and len(source) == 1
i_file = file(target[0].abspath, 'w')
name = str(source[0].get_contents())
param = all_params[name]
for line in param.swig_decl():
print >>i_file, line
def createEnumStrings(target, source, env):
assert len(target) == 1 and len(source) == 1
cc_file = file(target[0].abspath, 'w')
name = str(source[0].get_contents())
obj = all_enums[name]
print >>cc_file, obj.cxx_def()
cc_file.close()
def createEnumParam(target, source, env):
assert len(target) == 1 and len(source) == 1
hh_file = file(target[0].abspath, 'w')
name = str(source[0].get_contents())
obj = all_enums[name]
print >>hh_file, obj.cxx_decl()
# Generate all of the SimObject param struct header files
params_hh_files = []
for name,simobj in generate.sim_objects.iteritems():
extra_deps = [ File(generate.py_modules[simobj.__module__]) ]
for name,simobj in sim_objects.iteritems():
extra_deps = [ File(py_modules[simobj.__module__]) ]
hh_file = File('params/%s.hh' % name)
params_hh_files.append(hh_file)
env.Command(hh_file, Value(name), generate.createSimObjectParam)
env.Command(hh_file, Value(name), createSimObjectParam)
env.Depends(hh_file, depends + extra_deps)
# Generate any parameter header files needed
for name,param in generate.params.iteritems():
params_i_files = []
for name,param in all_params.iteritems():
if isinstance(param, m5.params.VectorParamDesc):
ext = 'vptype'
else:
ext = 'ptype'
i_file = File('params/%s_%s.i' % (name, ext))
env.Command(i_file, Value(name), generate.createSwigParam)
params_i_files.append(i_file)
env.Command(i_file, Value(name), createSwigParam)
env.Depends(i_file, depends)
# Generate all enum header files
for name,enum in generate.enums.iteritems():
extra_deps = [ File(generate.py_modules[enum.__module__]) ]
for name,enum in all_enums.iteritems():
extra_deps = [ File(py_modules[enum.__module__]) ]
cc_file = File('enums/%s.cc' % name)
env.Command(cc_file, Value(name), generate.createEnumStrings)
env.Command(cc_file, Value(name), createEnumStrings)
env.Depends(cc_file, depends + extra_deps)
Source(cc_file)
hh_file = File('enums/%s.hh' % name)
env.Command(hh_file, Value(name), generate.createEnumParam)
env.Command(hh_file, Value(name), createEnumParam)
env.Depends(hh_file, depends + extra_deps)
# Build the big monolithic swigged params module (wraps all SimObject
# param structs and enum structs)
def buildParams(target, source, env):
names = [ s.get_contents() for s in source ]
objs = [ sim_objects[name] for name in names ]
out = file(target[0].abspath, 'w')
ordered_objs = []
obj_seen = set()
def order_obj(obj):
name = str(obj)
if name in obj_seen:
return
obj_seen.add(name)
if str(obj) != 'SimObject':
order_obj(obj.__bases__[0])
ordered_objs.append(obj)
for obj in objs:
order_obj(obj)
enums = set()
predecls = []
pd_seen = set()
def add_pds(*pds):
for pd in pds:
if pd not in pd_seen:
predecls.append(pd)
pd_seen.add(pd)
for obj in ordered_objs:
params = obj._params.local.values()
for param in params:
ptype = param.ptype
if issubclass(ptype, m5.params.Enum):
if ptype not in enums:
enums.add(ptype)
pds = param.swig_predecls()
if isinstance(pds, (list, tuple)):
add_pds(*pds)
else:
add_pds(pds)
print >>out, '%module params'
print >>out, '%{'
for obj in ordered_objs:
print >>out, '#include "params/%s.hh"' % obj
print >>out, '%}'
for pd in predecls:
print >>out, pd
enums = list(enums)
enums.sort()
for enum in enums:
print >>out, '%%include "enums/%s.hh"' % enum.__name__
print >>out
for obj in ordered_objs:
if obj.swig_objdecls:
for decl in obj.swig_objdecls:
print >>out, decl
continue
class_path = obj.cxx_class.split('::')
classname = class_path[-1]
namespaces = class_path[:-1]
namespaces.reverse()
code = ''
if namespaces:
code += '// avoid name conflicts\n'
sep_string = '_COLONS_'
flat_name = sep_string.join(class_path)
code += '%%rename(%s) %s;\n' % (flat_name, classname)
code += '// stop swig from creating/wrapping default ctor/dtor\n'
code += '%%nodefault %s;\n' % classname
code += 'class %s ' % classname
if obj._base:
code += ': public %s' % obj._base.cxx_class
code += ' {};\n'
for ns in namespaces:
new_code = 'namespace %s {\n' % ns
new_code += code
new_code += '}\n'
code = new_code
print >>out, code
print >>out, '%%include "src/sim/sim_object_params.hh"' % obj
for obj in ordered_objs:
print >>out, '%%include "params/%s.hh"' % obj
params_file = File('params/params.i')
names = sort_list(generate.sim_objects.keys())
env.Command(params_file, [ Value(v) for v in names ],
generate.buildParams)
env.Depends(params_file, params_hh_files + depends)
names = sort_list(sim_objects.keys())
env.Command(params_file, [ Value(v) for v in names ], buildParams)
env.Depends(params_file, params_hh_files + params_i_files + depends)
SwigSource('m5.objects', params_file)
# Build all swig modules
swig_modules = []
cc_swig_sources = []
for source,package in swig_sources:
filename = str(source)
assert filename.endswith('.i')
@ -316,37 +600,316 @@ for source,package in swig_sources:
env.Depends(cc_file, source)
swig_modules.append(Value(module))
Source(cc_file)
cc_swig_sources.append(File(cc_file))
PySource(package, py_file)
# Generate the main swig init file
env.Command('swig/init.cc', swig_modules, generate.makeSwigInit)
Source('swig/init.cc')
def makeSwigInit(target, source, env):
f = file(str(target[0]), 'w')
print >>f, 'extern "C" {'
for module in source:
print >>f, ' void init_%s();' % module.get_contents()
print >>f, '}'
print >>f, 'void initSwig() {'
for module in source:
print >>f, ' init_%s();' % module.get_contents()
print >>f, '}'
f.close()
env.Command('python/swig/init.cc', swig_modules, makeSwigInit)
Source('python/swig/init.cc')
# Generate traceflags.py
flags = [ Value(f) for f in trace_flags ]
env.Command('base/traceflags.py', flags, generate.traceFlagsPy)
def traceFlagsPy(target, source, env):
assert(len(target) == 1)
f = file(str(target[0]), 'w')
allFlags = []
for s in source:
val = eval(s.get_contents())
allFlags.append(val)
allFlags.sort()
print >>f, 'basic = ['
for flag, compound, desc in allFlags:
if not compound:
print >>f, " '%s'," % flag
print >>f, " ]"
print >>f
print >>f, 'compound = ['
print >>f, " 'All',"
for flag, compound, desc in allFlags:
if compound:
print >>f, " '%s'," % flag
print >>f, " ]"
print >>f
print >>f, "all = frozenset(basic + compound)"
print >>f
print >>f, 'compoundMap = {'
all = tuple([flag for flag,compound,desc in allFlags if not compound])
print >>f, " 'All' : %s," % (all, )
for flag, compound, desc in allFlags:
if compound:
print >>f, " '%s' : %s," % (flag, compound)
print >>f, " }"
print >>f
print >>f, 'descriptions = {'
print >>f, " 'All' : 'All flags',"
for flag, compound, desc in allFlags:
print >>f, " '%s' : '%s'," % (flag, desc)
print >>f, " }"
f.close()
def traceFlagsCC(target, source, env):
assert(len(target) == 1)
f = file(str(target[0]), 'w')
allFlags = []
for s in source:
val = eval(s.get_contents())
allFlags.append(val)
# file header
print >>f, '''
/*
* DO NOT EDIT THIS FILE! Automatically generated
*/
#include "base/traceflags.hh"
using namespace Trace;
const char *Trace::flagStrings[] =
{'''
# The string array is used by SimpleEnumParam to map the strings
# provided by the user to enum values.
for flag, compound, desc in allFlags:
if not compound:
print >>f, ' "%s",' % flag
print >>f, ' "All",'
for flag, compound, desc in allFlags:
if compound:
print >>f, ' "%s",' % flag
print >>f, '};'
print >>f
print >>f, 'const int Trace::numFlagStrings = %d;' % (len(allFlags) + 1)
print >>f
#
# Now define the individual compound flag arrays. There is an array
# for each compound flag listing the component base flags.
#
all = tuple([flag for flag,compound,desc in allFlags if not compound])
print >>f, 'static const Flags AllMap[] = {'
for flag, compound, desc in allFlags:
if not compound:
print >>f, " %s," % flag
print >>f, '};'
print >>f
for flag, compound, desc in allFlags:
if not compound:
continue
print >>f, 'static const Flags %sMap[] = {' % flag
for flag in compound:
print >>f, " %s," % flag
print >>f, " (Flags)-1"
print >>f, '};'
print >>f
#
# Finally the compoundFlags[] array maps the compound flags
# to their individual arrays/
#
print >>f, 'const Flags *Trace::compoundFlags[] ='
print >>f, '{'
print >>f, ' AllMap,'
for flag, compound, desc in allFlags:
if compound:
print >>f, ' %sMap,' % flag
# file trailer
print >>f, '};'
f.close()
def traceFlagsHH(target, source, env):
assert(len(target) == 1)
f = file(str(target[0]), 'w')
allFlags = []
for s in source:
val = eval(s.get_contents())
allFlags.append(val)
# file header boilerplate
print >>f, '''
/*
* DO NOT EDIT THIS FILE!
*
* Automatically generated from traceflags.py
*/
#ifndef __BASE_TRACE_FLAGS_HH__
#define __BASE_TRACE_FLAGS_HH__
namespace Trace {
enum Flags {'''
# Generate the enum. Base flags come first, then compound flags.
idx = 0
for flag, compound, desc in allFlags:
if not compound:
print >>f, ' %s = %d,' % (flag, idx)
idx += 1
numBaseFlags = idx
print >>f, ' NumFlags = %d,' % idx
# put a comment in here to separate base from compound flags
print >>f, '''
// The remaining enum values are *not* valid indices for Trace::flags.
// They are "compound" flags, which correspond to sets of base
// flags, and are used by changeFlag.'''
print >>f, ' All = %d,' % idx
idx += 1
for flag, compound, desc in allFlags:
if compound:
print >>f, ' %s = %d,' % (flag, idx)
idx += 1
numCompoundFlags = idx - numBaseFlags
print >>f, ' NumCompoundFlags = %d' % numCompoundFlags
# trailer boilerplate
print >>f, '''\
}; // enum Flags
// Array of strings for SimpleEnumParam
extern const char *flagStrings[];
extern const int numFlagStrings;
// Array of arraay pointers: for each compound flag, gives the list of
// base flags to set. Inidividual flag arrays are terminated by -1.
extern const Flags *compoundFlags[];
/* namespace Trace */ }
#endif // __BASE_TRACE_FLAGS_HH__
'''
f.close()
flags = [ Value(f) for f in trace_flags.values() ]
env.Command('base/traceflags.py', flags, traceFlagsPy)
PySource('m5', 'base/traceflags.py')
env.Command('base/traceflags.hh', flags, generate.traceFlagsHH)
env.Command('base/traceflags.cc', flags, generate.traceFlagsCC)
env.Command('base/traceflags.hh', flags, traceFlagsHH)
env.Command('base/traceflags.cc', flags, traceFlagsCC)
Source('base/traceflags.cc')
# Build the zip file
py_compiled = []
py_zip_depends = []
# embed python files. All .py files that have been indicated by a
# PySource() call in a SConscript need to be embedded into the M5
# library. To do that, we compile the file to byte code, marshal the
# byte code, compress it, and then generate an assembly file that
# inserts the result into the data section with symbols indicating the
# beginning, and end (and with the size at the end)
py_sources_tnodes = {}
for pysource in py_sources:
py_sources_tnodes[pysource.tnode] = pysource
def objectifyPyFile(target, source, env):
'''Action function to compile a .py into a code object, marshal
it, compress it, and stick it into an asm file so the code appears
as just bytes with a label in the data section'''
src = file(str(source[0]), 'r').read()
dst = file(str(target[0]), 'w')
pysource = py_sources_tnodes[source[0]]
compiled = compile(src, pysource.debugname, 'exec')
marshalled = marshal.dumps(compiled)
compressed = zlib.compress(marshalled)
data = compressed
# Some C/C++ compilers prepend an underscore to global symbol
# names, so if they're going to do that, we need to prepend that
# leading underscore to globals in the assembly file.
if env['LEADING_UNDERSCORE']:
sym = '_' + pysource.symname
else:
sym = pysource.symname
step = 16
print >>dst, ".data"
print >>dst, ".globl %s_beg" % sym
print >>dst, ".globl %s_end" % sym
print >>dst, "%s_beg:" % sym
for i in xrange(0, len(data), step):
x = array.array('B', data[i:i+step])
print >>dst, ".byte", ','.join([str(d) for d in x])
print >>dst, "%s_end:" % sym
print >>dst, ".long %d" % len(marshalled)
for source in py_sources:
env.Command(source.compiled, source.source, generate.compilePyFile)
py_compiled.append(source.compiled)
env.Command(source.assembly, source.tnode, objectifyPyFile)
Source(source.assembly)
# make the zipfile depend on the archive name so that the archive
# is rebuilt if the name changes
py_zip_depends.append(Value(source.arcname))
# Generate init_python.cc which creates a bunch of EmbeddedPyModule
# structs that describe the embedded python code. One such struct
# contains information about the importer that python uses to get at
# the embedded files, and then there's a list of all of the rest that
# the importer uses to load the rest on demand.
py_sources_symbols = {}
for pysource in py_sources:
py_sources_symbols[pysource.symname] = pysource
def pythonInit(target, source, env):
dst = file(str(target[0]), 'w')
# Add the zip file target to the environment.
m5zip = File('m5py.zip')
env.Command(m5zip, py_compiled, generate.buildPyZip)
env.Depends(m5zip, py_zip_depends)
def dump_mod(sym, endchar=','):
pysource = py_sources_symbols[sym]
print >>dst, ' { "%s",' % pysource.arcname
print >>dst, ' "%s",' % pysource.modpath
print >>dst, ' %s_beg, %s_end,' % (sym, sym)
print >>dst, ' %s_end - %s_beg,' % (sym, sym)
print >>dst, ' *(int *)%s_end }%s' % (sym, endchar)
print >>dst, '#include "sim/init.hh"'
for sym in source:
sym = sym.get_contents()
print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym)
print >>dst, "const EmbeddedPyModule embeddedPyImporter = "
dump_mod("PyEMB_importer", endchar=';');
print >>dst
print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {"
for i,sym in enumerate(source):
sym = sym.get_contents()
if sym == "PyEMB_importer":
# Skip the importer since we've already exported it
continue
dump_mod(sym)
print >>dst, " { 0, 0, 0, 0, 0, 0 }"
print >>dst, "};"
symbols = [Value(s.symname) for s in py_sources]
env.Command('sim/init_python.cc', symbols, pythonInit)
Source('sim/init_python.cc')
########################################################################
#
@ -362,11 +925,18 @@ envList = []
# Object nodes (including an extra one for date.cc). We explicitly
# add the Object nodes so we can set up special dependencies for
# date.cc.
def make_objs(sources, env):
objs = [env.Object(s) for s in sources]
def make_objs(sources, env, static):
if static:
XObject = env.StaticObject
else:
XObject = env.SharedObject
objs = [ XObject(s) for s in sources ]
# make date.cc depend on all other objects so it always gets
# recompiled whenever anything else does
date_obj = env.Object('base/date.cc')
date_obj = XObject('base/date.cc')
env.Depends(date_obj, objs)
objs.append(date_obj)
return objs
@ -376,23 +946,50 @@ def make_objs(sources, env):
# binary. Additional keyword arguments are appended to corresponding
# build environment vars.
def makeEnv(label, objsfx, strip = False, **kwargs):
newEnv = env.Copy(OBJSUFFIX=objsfx)
newEnv.Label = label
newEnv.Append(**kwargs)
exe = 'm5.' + label # final executable
bin = exe + '.bin' # executable w/o appended Python zip archive
newEnv.Program(bin, make_objs(cc_sources, newEnv))
# SCons doesn't know to append a library suffix when there is a '.' in the
# name. Use '_' instead.
libname = 'm5_' + label
exename = 'm5.' + label
new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
new_env.Label = label
new_env.Append(**kwargs)
swig_env = new_env.Clone()
if env['GCC']:
swig_env.Append(CCFLAGS='-Wno-uninitialized')
swig_env.Append(CCFLAGS='-Wno-sign-compare')
swig_env.Append(CCFLAGS='-Wno-parentheses')
static_objs = make_objs(cc_lib_sources, new_env, static=True)
shared_objs = make_objs(cc_lib_sources, new_env, static=False)
static_objs += [ swig_env.StaticObject(s) for s in cc_swig_sources ]
shared_objs += [ swig_env.SharedObject(s) for s in cc_swig_sources ]
# First make a library of everything but main() so other programs can
# link against m5.
static_lib = new_env.StaticLibrary(libname, static_objs)
shared_lib = new_env.SharedLibrary(libname, shared_objs)
for target, sources in unit_tests:
objs = [ new_env.StaticObject(s) for s in sources ]
new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs)
# Now link a stub with main() and the static library.
objects = [new_env.Object(s) for s in cc_bin_sources] + static_objs
if strip:
stripped_bin = bin + '.stripped'
unstripped_exe = exename + '.unstripped'
new_env.Program(unstripped_exe, objects)
if sys.platform == 'sunos5':
cmd = 'cp $SOURCE $TARGET; strip $TARGET'
else:
cmd = 'strip $SOURCE -o $TARGET'
newEnv.Command(stripped_bin, bin, cmd)
bin = stripped_bin
targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
newEnv.M5Binary = targets[0]
envList.append(newEnv)
targets = new_env.Command(exename, unstripped_exe, cmd)
else:
targets = new_env.Program(exename, objects)
new_env.M5Binary = targets[0]
envList.append(new_env)
# Debug binary
ccflags = {}

View file

@ -49,13 +49,13 @@ isa_switch_hdrs = Split('''
isa_traits.hh
kernel_stats.hh
locked_mem.hh
microcode_rom.hh
mmaped_ipr.hh
process.hh
predecoder.hh
regfile.hh
remote_gdb.hh
stacktrace.hh
syscallreturn.hh
tlb.hh
types.hh
utility.hh
@ -125,3 +125,8 @@ else:
emitter = isa_desc_emitter)
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
TraceFlag('IntRegs')
TraceFlag('FloatRegs')
TraceFlag('MiscRegs')
CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'MiscRegs' ])

View file

@ -0,0 +1,33 @@
# Copyright (c) 2008 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Gabe Black
from m5.SimObject import SimObject
class AlphaInterrupts(SimObject):
type = 'AlphaInterrupts'
cxx_class = 'AlphaISA::Interrupts'

View file

@ -28,21 +28,20 @@
from m5.SimObject import SimObject
from m5.params import *
class AlphaTLB(SimObject):
from BaseTLB import BaseTLB
class AlphaTLB(BaseTLB):
type = 'AlphaTLB'
abstract = True
size = Param.Int("TLB size")
class AlphaDTB(AlphaTLB):
type = 'AlphaDTB'
cxx_namespace = 'AlphaISA'
cxx_class = 'DTB'
cxx_class = 'AlphaISA::DTB'
size = 64
class AlphaITB(AlphaTLB):
type = 'AlphaITB'
cxx_namespace = 'AlphaISA'
cxx_class = 'ITB'
cxx_class = 'AlphaISA::ITB'
size = 48

View file

@ -47,9 +47,11 @@ if env['TARGET_ISA'] == 'alpha':
SimObject('AlphaTLB.py')
if env['FULL_SYSTEM']:
SimObject('AlphaInterrupts.py')
SimObject('AlphaSystem.py')
Source('idle_event.cc')
Source('interrupts.cc')
Source('kernel_stats.cc')
Source('osfpal.cc')
Source('stacktrace.cc')

View file

@ -33,5 +33,5 @@ Import('*')
all_isa_list.append('alpha')
# Alpha can be compiled with Turbolaser support instead of Tsunami
sticky_opts.Add(BoolOption('ALPHA_TLASER',
sticky_vars.Add(BoolVariable('ALPHA_TLASER',
'Model Alpha TurboLaser platform (vs. Tsunami)', False))

View file

@ -35,32 +35,33 @@
#include "arch/alpha/osfpal.hh"
#include "arch/alpha/tlb.hh"
#include "arch/alpha/kgdb.h"
#include "base/cp_annotate.hh"
#include "base/debug.hh"
#include "base/remote_gdb.hh"
#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "sim/debug.hh"
#include "sim/sim_exit.hh"
#if FULL_SYSTEM
namespace AlphaISA {
using namespace EV5;
#if FULL_SYSTEM
////////////////////////////////////////////////////////////////////////
//
// Machine dependent functions
//
void
AlphaISA::initCPU(ThreadContext *tc, int cpuId)
initCPU(ThreadContext *tc, int cpuId)
{
initIPRs(tc, cpuId);
tc->setIntReg(16, cpuId);
tc->setIntReg(0, cpuId);
AlphaISA::AlphaFault *reset = new AlphaISA::ResetFault;
AlphaFault *reset = new ResetFault;
tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect());
tc->setNextPC(tc->readPC() + sizeof(MachInst));
@ -71,7 +72,7 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId)
template <class CPU>
void
AlphaISA::processInterrupts(CPU *cpu)
processInterrupts(CPU *cpu)
{
//Check if there are any outstanding interrupts
//Handle the interrupts
@ -117,7 +118,7 @@ AlphaISA::processInterrupts(CPU *cpu)
template <class CPU>
void
AlphaISA::zeroRegisters(CPU *cpu)
zeroRegisters(CPU *cpu)
{
// Insure ISA semantics
// (no longer very clean due to the change in setIntReg() in the
@ -126,33 +127,16 @@ AlphaISA::zeroRegisters(CPU *cpu)
cpu->thread->setFloatReg(ZeroReg, 0.0);
}
Fault
SimpleThread::hwrei()
int
MiscRegFile::getInstAsid()
{
if (!(readPC() & 0x3))
return new UnimplementedOpcodeFault;
setNextPC(readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR));
if (!misspeculating()) {
if (kernelStats)
kernelStats->hwrei();
}
// FIXME: XXX check for interrupts? XXX
return NoFault;
return ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
}
int
AlphaISA::MiscRegFile::getInstAsid()
MiscRegFile::getDataAsid()
{
return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
}
int
AlphaISA::MiscRegFile::getDataAsid()
{
return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
return DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
}
#endif
@ -162,90 +146,90 @@ AlphaISA::MiscRegFile::getDataAsid()
//
//
void
AlphaISA::initIPRs(ThreadContext *tc, int cpuId)
initIPRs(ThreadContext *tc, int cpuId)
{
for (int i = 0; i < NumInternalProcRegs; ++i) {
tc->setMiscRegNoEffect(i, 0);
}
tc->setMiscRegNoEffect(IPR_PAL_BASE, EV5::PalBase);
tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase);
tc->setMiscRegNoEffect(IPR_MCSR, 0x6);
tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId);
}
AlphaISA::MiscReg
AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc)
MiscReg
MiscRegFile::readIpr(int idx, ThreadContext *tc)
{
uint64_t retval = 0; // return value, default 0
switch (idx) {
case AlphaISA::IPR_PALtemp0:
case AlphaISA::IPR_PALtemp1:
case AlphaISA::IPR_PALtemp2:
case AlphaISA::IPR_PALtemp3:
case AlphaISA::IPR_PALtemp4:
case AlphaISA::IPR_PALtemp5:
case AlphaISA::IPR_PALtemp6:
case AlphaISA::IPR_PALtemp7:
case AlphaISA::IPR_PALtemp8:
case AlphaISA::IPR_PALtemp9:
case AlphaISA::IPR_PALtemp10:
case AlphaISA::IPR_PALtemp11:
case AlphaISA::IPR_PALtemp12:
case AlphaISA::IPR_PALtemp13:
case AlphaISA::IPR_PALtemp14:
case AlphaISA::IPR_PALtemp15:
case AlphaISA::IPR_PALtemp16:
case AlphaISA::IPR_PALtemp17:
case AlphaISA::IPR_PALtemp18:
case AlphaISA::IPR_PALtemp19:
case AlphaISA::IPR_PALtemp20:
case AlphaISA::IPR_PALtemp21:
case AlphaISA::IPR_PALtemp22:
case AlphaISA::IPR_PALtemp23:
case AlphaISA::IPR_PAL_BASE:
case IPR_PALtemp0:
case IPR_PALtemp1:
case IPR_PALtemp2:
case IPR_PALtemp3:
case IPR_PALtemp4:
case IPR_PALtemp5:
case IPR_PALtemp6:
case IPR_PALtemp7:
case IPR_PALtemp8:
case IPR_PALtemp9:
case IPR_PALtemp10:
case IPR_PALtemp11:
case IPR_PALtemp12:
case IPR_PALtemp13:
case IPR_PALtemp14:
case IPR_PALtemp15:
case IPR_PALtemp16:
case IPR_PALtemp17:
case IPR_PALtemp18:
case IPR_PALtemp19:
case IPR_PALtemp20:
case IPR_PALtemp21:
case IPR_PALtemp22:
case IPR_PALtemp23:
case IPR_PAL_BASE:
case AlphaISA::IPR_IVPTBR:
case AlphaISA::IPR_DC_MODE:
case AlphaISA::IPR_MAF_MODE:
case AlphaISA::IPR_ISR:
case AlphaISA::IPR_EXC_ADDR:
case AlphaISA::IPR_IC_PERR_STAT:
case AlphaISA::IPR_DC_PERR_STAT:
case AlphaISA::IPR_MCSR:
case AlphaISA::IPR_ASTRR:
case AlphaISA::IPR_ASTER:
case AlphaISA::IPR_SIRR:
case AlphaISA::IPR_ICSR:
case AlphaISA::IPR_ICM:
case AlphaISA::IPR_DTB_CM:
case AlphaISA::IPR_IPLR:
case AlphaISA::IPR_INTID:
case AlphaISA::IPR_PMCTR:
case IPR_IVPTBR:
case IPR_DC_MODE:
case IPR_MAF_MODE:
case IPR_ISR:
case IPR_EXC_ADDR:
case IPR_IC_PERR_STAT:
case IPR_DC_PERR_STAT:
case IPR_MCSR:
case IPR_ASTRR:
case IPR_ASTER:
case IPR_SIRR:
case IPR_ICSR:
case IPR_ICM:
case IPR_DTB_CM:
case IPR_IPLR:
case IPR_INTID:
case IPR_PMCTR:
// no side-effect
retval = ipr[idx];
break;
case AlphaISA::IPR_CC:
case IPR_CC:
retval |= ipr[idx] & ULL(0xffffffff00000000);
retval |= tc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff);
break;
case AlphaISA::IPR_VA:
case IPR_VA:
retval = ipr[idx];
break;
case AlphaISA::IPR_VA_FORM:
case AlphaISA::IPR_MM_STAT:
case AlphaISA::IPR_IFAULT_VA_FORM:
case AlphaISA::IPR_EXC_MASK:
case AlphaISA::IPR_EXC_SUM:
case IPR_VA_FORM:
case IPR_MM_STAT:
case IPR_IFAULT_VA_FORM:
case IPR_EXC_MASK:
case IPR_EXC_SUM:
retval = ipr[idx];
break;
case AlphaISA::IPR_DTB_PTE:
case IPR_DTB_PTE:
{
AlphaISA::TlbEntry &entry
TlbEntry &entry
= tc->getDTBPtr()->index(!tc->misspeculating());
retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32;
@ -259,15 +243,15 @@ AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc)
break;
// write only registers
case AlphaISA::IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT:
case AlphaISA::IPR_DC_FLUSH:
case AlphaISA::IPR_IC_FLUSH:
case AlphaISA::IPR_ALT_MODE:
case AlphaISA::IPR_DTB_IA:
case AlphaISA::IPR_DTB_IAP:
case AlphaISA::IPR_ITB_IA:
case AlphaISA::IPR_ITB_IAP:
case IPR_HWINT_CLR:
case IPR_SL_XMIT:
case IPR_DC_FLUSH:
case IPR_IC_FLUSH:
case IPR_ALT_MODE:
case IPR_DTB_IA:
case IPR_DTB_IAP:
case IPR_ITB_IA:
case IPR_ITB_IAP:
panic("Tried to read write only register %d\n", idx);
break;
@ -286,7 +270,7 @@ int break_ipl = -1;
#endif
void
AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
{
uint64_t old;
@ -294,52 +278,52 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
return;
switch (idx) {
case AlphaISA::IPR_PALtemp0:
case AlphaISA::IPR_PALtemp1:
case AlphaISA::IPR_PALtemp2:
case AlphaISA::IPR_PALtemp3:
case AlphaISA::IPR_PALtemp4:
case AlphaISA::IPR_PALtemp5:
case AlphaISA::IPR_PALtemp6:
case AlphaISA::IPR_PALtemp7:
case AlphaISA::IPR_PALtemp8:
case AlphaISA::IPR_PALtemp9:
case AlphaISA::IPR_PALtemp10:
case AlphaISA::IPR_PALtemp11:
case AlphaISA::IPR_PALtemp12:
case AlphaISA::IPR_PALtemp13:
case AlphaISA::IPR_PALtemp14:
case AlphaISA::IPR_PALtemp15:
case AlphaISA::IPR_PALtemp16:
case AlphaISA::IPR_PALtemp17:
case AlphaISA::IPR_PALtemp18:
case AlphaISA::IPR_PALtemp19:
case AlphaISA::IPR_PALtemp20:
case AlphaISA::IPR_PALtemp21:
case AlphaISA::IPR_PALtemp22:
case AlphaISA::IPR_PAL_BASE:
case AlphaISA::IPR_IC_PERR_STAT:
case AlphaISA::IPR_DC_PERR_STAT:
case AlphaISA::IPR_PMCTR:
case IPR_PALtemp0:
case IPR_PALtemp1:
case IPR_PALtemp2:
case IPR_PALtemp3:
case IPR_PALtemp4:
case IPR_PALtemp5:
case IPR_PALtemp6:
case IPR_PALtemp7:
case IPR_PALtemp8:
case IPR_PALtemp9:
case IPR_PALtemp10:
case IPR_PALtemp11:
case IPR_PALtemp12:
case IPR_PALtemp13:
case IPR_PALtemp14:
case IPR_PALtemp15:
case IPR_PALtemp16:
case IPR_PALtemp17:
case IPR_PALtemp18:
case IPR_PALtemp19:
case IPR_PALtemp20:
case IPR_PALtemp21:
case IPR_PALtemp22:
case IPR_PAL_BASE:
case IPR_IC_PERR_STAT:
case IPR_DC_PERR_STAT:
case IPR_PMCTR:
// write entire quad w/ no side-effect
ipr[idx] = val;
break;
case AlphaISA::IPR_CC_CTL:
case IPR_CC_CTL:
// This IPR resets the cycle counter. We assume this only
// happens once... let's verify that.
assert(ipr[idx] == 0);
ipr[idx] = 1;
break;
case AlphaISA::IPR_CC:
case IPR_CC:
// This IPR only writes the upper 64 bits. It's ok to write
// all 64 here since we mask out the lower 32 in rpcc (see
// isa_desc).
ipr[idx] = val;
break;
case AlphaISA::IPR_PALtemp23:
case IPR_PALtemp23:
// write entire quad w/ no side-effect
old = ipr[idx];
ipr[idx] = val;
@ -349,23 +333,23 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
#endif
break;
case AlphaISA::IPR_DTB_PTE:
case IPR_DTB_PTE:
// write entire quad w/ no side-effect, tag is forthcoming
ipr[idx] = val;
break;
case AlphaISA::IPR_EXC_ADDR:
case IPR_EXC_ADDR:
// second least significant bit in PC is always zero
ipr[idx] = val & ~2;
break;
case AlphaISA::IPR_ASTRR:
case AlphaISA::IPR_ASTER:
case IPR_ASTRR:
case IPR_ASTER:
// only write least significant four bits - privilege mask
ipr[idx] = val & 0xf;
break;
case AlphaISA::IPR_IPLR:
case IPR_IPLR:
#ifdef DEBUG
if (break_ipl != -1 && break_ipl == (val & 0x1f))
debug_break();
@ -379,175 +363,173 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
#endif
break;
case AlphaISA::IPR_DTB_CM:
case IPR_DTB_CM:
#if FULL_SYSTEM
if (val & 0x18) {
if (tc->getKernelStats())
tc->getKernelStats()->mode(TheISA::Kernel::user, tc);
tc->getKernelStats()->mode(Kernel::user, tc);
} else {
if (tc->getKernelStats())
tc->getKernelStats()->mode(TheISA::Kernel::kernel, tc);
tc->getKernelStats()->mode(Kernel::kernel, tc);
}
#endif
case AlphaISA::IPR_ICM:
case IPR_ICM:
// only write two mode bits - processor mode
ipr[idx] = val & 0x18;
break;
case AlphaISA::IPR_ALT_MODE:
case IPR_ALT_MODE:
// only write two mode bits - processor mode
ipr[idx] = val & 0x18;
break;
case AlphaISA::IPR_MCSR:
case IPR_MCSR:
// more here after optimization...
ipr[idx] = val;
break;
case AlphaISA::IPR_SIRR:
case IPR_SIRR:
// only write software interrupt mask
ipr[idx] = val & 0x7fff0;
break;
case AlphaISA::IPR_ICSR:
case IPR_ICSR:
ipr[idx] = val & ULL(0xffffff0300);
break;
case AlphaISA::IPR_IVPTBR:
case AlphaISA::IPR_MVPTBR:
case IPR_IVPTBR:
case IPR_MVPTBR:
ipr[idx] = val & ULL(0xffffffffc0000000);
break;
case AlphaISA::IPR_DC_TEST_CTL:
case IPR_DC_TEST_CTL:
ipr[idx] = val & 0x1ffb;
break;
case AlphaISA::IPR_DC_MODE:
case AlphaISA::IPR_MAF_MODE:
case IPR_DC_MODE:
case IPR_MAF_MODE:
ipr[idx] = val & 0x3f;
break;
case AlphaISA::IPR_ITB_ASN:
case IPR_ITB_ASN:
ipr[idx] = val & 0x7f0;
break;
case AlphaISA::IPR_DTB_ASN:
case IPR_DTB_ASN:
ipr[idx] = val & ULL(0xfe00000000000000);
break;
case AlphaISA::IPR_EXC_SUM:
case AlphaISA::IPR_EXC_MASK:
case IPR_EXC_SUM:
case IPR_EXC_MASK:
// any write to this register clears it
ipr[idx] = 0;
break;
case AlphaISA::IPR_INTID:
case AlphaISA::IPR_SL_RCV:
case AlphaISA::IPR_MM_STAT:
case AlphaISA::IPR_ITB_PTE_TEMP:
case AlphaISA::IPR_DTB_PTE_TEMP:
case IPR_INTID:
case IPR_SL_RCV:
case IPR_MM_STAT:
case IPR_ITB_PTE_TEMP:
case IPR_DTB_PTE_TEMP:
// read-only registers
panic("Tried to write read only ipr %d\n", idx);
case AlphaISA::IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT:
case AlphaISA::IPR_DC_FLUSH:
case AlphaISA::IPR_IC_FLUSH:
case IPR_HWINT_CLR:
case IPR_SL_XMIT:
case IPR_DC_FLUSH:
case IPR_IC_FLUSH:
// the following are write only
ipr[idx] = val;
break;
case AlphaISA::IPR_DTB_IA:
case IPR_DTB_IA:
// really a control write
ipr[idx] = 0;
tc->getDTBPtr()->flushAll();
break;
case AlphaISA::IPR_DTB_IAP:
case IPR_DTB_IAP:
// really a control write
ipr[idx] = 0;
tc->getDTBPtr()->flushProcesses();
break;
case AlphaISA::IPR_DTB_IS:
case IPR_DTB_IS:
// really a control write
ipr[idx] = val;
tc->getDTBPtr()->flushAddr(val,
EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
tc->getDTBPtr()->flushAddr(val, DTB_ASN_ASN(ipr[IPR_DTB_ASN]));
break;
case AlphaISA::IPR_DTB_TAG: {
struct AlphaISA::TlbEntry entry;
case IPR_DTB_TAG: {
struct TlbEntry entry;
// FIXME: granularity hints NYI...
if (EV5::DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0)
if (DTB_PTE_GH(ipr[IPR_DTB_PTE]) != 0)
panic("PTE GH field != 0");
// write entire quad
ipr[idx] = val;
// construct PTE for new entry
entry.ppn = EV5::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
entry.xre = EV5::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
entry.xwe = EV5::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
entry.fonr = EV5::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
entry.fonw = EV5::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
entry.asma = EV5::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
entry.asn = EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
entry.ppn = DTB_PTE_PPN(ipr[IPR_DTB_PTE]);
entry.xre = DTB_PTE_XRE(ipr[IPR_DTB_PTE]);
entry.xwe = DTB_PTE_XWE(ipr[IPR_DTB_PTE]);
entry.fonr = DTB_PTE_FONR(ipr[IPR_DTB_PTE]);
entry.fonw = DTB_PTE_FONW(ipr[IPR_DTB_PTE]);
entry.asma = DTB_PTE_ASMA(ipr[IPR_DTB_PTE]);
entry.asn = DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
// insert new TAG/PTE value into data TLB
tc->getDTBPtr()->insert(val, entry);
}
break;
case AlphaISA::IPR_ITB_PTE: {
struct AlphaISA::TlbEntry entry;
case IPR_ITB_PTE: {
struct TlbEntry entry;
// FIXME: granularity hints NYI...
if (EV5::ITB_PTE_GH(val) != 0)
if (ITB_PTE_GH(val) != 0)
panic("PTE GH field != 0");
// write entire quad
ipr[idx] = val;
// construct PTE for new entry
entry.ppn = EV5::ITB_PTE_PPN(val);
entry.xre = EV5::ITB_PTE_XRE(val);
entry.ppn = ITB_PTE_PPN(val);
entry.xre = ITB_PTE_XRE(val);
entry.xwe = 0;
entry.fonr = EV5::ITB_PTE_FONR(val);
entry.fonw = EV5::ITB_PTE_FONW(val);
entry.asma = EV5::ITB_PTE_ASMA(val);
entry.asn = EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
entry.fonr = ITB_PTE_FONR(val);
entry.fonw = ITB_PTE_FONW(val);
entry.asma = ITB_PTE_ASMA(val);
entry.asn = ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
// insert new TAG/PTE value into data TLB
tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], entry);
tc->getITBPtr()->insert(ipr[IPR_ITB_TAG], entry);
}
break;
case AlphaISA::IPR_ITB_IA:
case IPR_ITB_IA:
// really a control write
ipr[idx] = 0;
tc->getITBPtr()->flushAll();
break;
case AlphaISA::IPR_ITB_IAP:
case IPR_ITB_IAP:
// really a control write
ipr[idx] = 0;
tc->getITBPtr()->flushProcesses();
break;
case AlphaISA::IPR_ITB_IS:
case IPR_ITB_IS:
// really a control write
ipr[idx] = val;
tc->getITBPtr()->flushAddr(val,
EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
tc->getITBPtr()->flushAddr(val, ITB_ASN_ASN(ipr[IPR_ITB_ASN]));
break;
default:
@ -558,17 +540,38 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc)
// no error...
}
void
AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest)
copyIprs(ThreadContext *src, ThreadContext *dest)
{
for (int i = 0; i < NumInternalProcRegs; ++i) {
for (int i = 0; i < NumInternalProcRegs; ++i)
dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
}
}
} // namespace AlphaISA
#if FULL_SYSTEM
using namespace AlphaISA;
Fault
SimpleThread::hwrei()
{
if (!(readPC() & 0x3))
return new UnimplementedOpcodeFault;
setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR));
CPA::cpa()->swAutoBegin(tc, readNextPC());
if (!misspeculating()) {
if (kernelStats)
kernelStats->hwrei();
}
// FIXME: XXX check for interrupts? XXX
return NoFault;
}
/**
* Check for special simulator handling of specific PAL calls.
* If return value is false, actual PAL call will be suppressed.

View file

@ -36,10 +36,7 @@
#include "config/alpha_tlaser.hh"
#include "arch/alpha/isa_traits.hh"
namespace EV5 {
//It seems like a safe assumption EV5 only applies to alpha
using namespace AlphaISA;
namespace AlphaISA {
#if ALPHA_TLASER
const uint64_t AsnMask = ULL(0x7f);
@ -51,8 +48,8 @@ const int VAddrImplBits = 43;
const Addr VAddrImplMask = (ULL(1) << VAddrImplBits) - 1;
const Addr VAddrUnImplMask = ~VAddrImplMask;
inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
inline Addr VAddrVPN(Addr a) { return a >> AlphaISA::PageShift; }
inline Addr VAddrOffset(Addr a) { return a & AlphaISA::PageOffset; }
inline Addr VAddrVPN(Addr a) { return a >> PageShift; }
inline Addr VAddrOffset(Addr a) { return a & PageOffset; }
inline Addr VAddrSpaceEV5(Addr a) { return a >> 41 & 0x3; }
inline Addr VAddrSpaceEV6(Addr a) { return a >> 41 & 0x7f; }
@ -68,7 +65,9 @@ const Addr PAddrUncachedBit39 = ULL(0x8000000000);
const Addr PAddrUncachedBit40 = ULL(0x10000000000);
const Addr PAddrUncachedBit43 = ULL(0x80000000000);
const Addr PAddrUncachedMask = ULL(0x807ffffffff); // Clear PA<42:35>
inline Addr Phys2K0Seg(Addr addr)
inline Addr
Phys2K0Seg(Addr addr)
{
#if !ALPHA_TLASER
if (addr & PAddrUncachedBit43) {
@ -76,12 +75,12 @@ inline Addr Phys2K0Seg(Addr addr)
addr |= PAddrUncachedBit40;
}
#endif
return addr | AlphaISA::K0SegBase;
return addr | K0SegBase;
}
inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; }
inline Addr DTB_PTE_PPN(uint64_t reg)
{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; }
{ return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); }
inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; }
inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; }
inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; }
@ -91,7 +90,7 @@ inline int DTB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; }
inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; }
inline Addr ITB_PTE_PPN(uint64_t reg)
{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; }
{ return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); }
inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; }
inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; }
inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; }
@ -114,12 +113,12 @@ const uint64_t MM_STAT_FONW_MASK = ULL(0x0008);
const uint64_t MM_STAT_FONR_MASK = ULL(0x0004);
const uint64_t MM_STAT_ACV_MASK = ULL(0x0002);
const uint64_t MM_STAT_WR_MASK = ULL(0x0001);
inline int Opcode(AlphaISA::MachInst inst) { return inst >> 26 & 0x3f; }
inline int Ra(AlphaISA::MachInst inst) { return inst >> 21 & 0x1f; }
inline int Opcode(MachInst inst) { return inst >> 26 & 0x3f; }
inline int Ra(MachInst inst) { return inst >> 21 & 0x1f; }
const Addr PalBase = 0x4000;
const Addr PalMax = 0x10000;
/* namespace EV5 */ }
} // namespace AlphaISA
#endif // __ARCH_ALPHA_EV5_HH__

View file

@ -40,8 +40,7 @@
#include "mem/page_table.hh"
#endif
namespace AlphaISA
{
namespace AlphaISA {
FaultName MachineCheckFault::_name = "mchk";
FaultVect MachineCheckFault::_vect = 0x0401;
@ -109,64 +108,67 @@ FaultStat IntegerOverflowFault::_count;
#if FULL_SYSTEM
void AlphaFault::invoke(ThreadContext * tc)
void
AlphaFault::invoke(ThreadContext *tc)
{
FaultBase::invoke(tc);
countStat()++;
// exception restart address
if (setRestartAddress() || !(tc->readPC() & 0x3))
tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, tc->readPC());
tc->setMiscRegNoEffect(IPR_EXC_ADDR, tc->readPC());
if (skipFaultingInstruction()) {
// traps... skip faulting instruction.
tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
tc->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR) + 4);
tc->setMiscRegNoEffect(IPR_EXC_ADDR,
tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4);
}
tc->setPC(tc->readMiscRegNoEffect(AlphaISA::IPR_PAL_BASE) + vect());
tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect());
tc->setNextPC(tc->readPC() + sizeof(MachInst));
}
void ArithmeticFault::invoke(ThreadContext * tc)
void
ArithmeticFault::invoke(ThreadContext *tc)
{
FaultBase::invoke(tc);
panic("Arithmetic traps are unimplemented!");
}
void DtbFault::invoke(ThreadContext * tc)
void
DtbFault::invoke(ThreadContext *tc)
{
// Set fault address and flags. Even though we're modeling an
// EV5, we use the EV6 technique of not latching fault registers
// on VPTE loads (instead of locking the registers until IPR_VA is
// read, like the EV5). The EV6 approach is cleaner and seems to
// work with EV5 PAL code, but not the other way around.
if (!tc->misspeculating()
&& !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) {
if (!tc->misspeculating() &&
reqFlags.noneSet(Request::VPTE|Request::NO_FAULT)) {
// set VA register with faulting address
tc->setMiscRegNoEffect(AlphaISA::IPR_VA, vaddr);
tc->setMiscRegNoEffect(IPR_VA, vaddr);
// set MM_STAT register flags
tc->setMiscRegNoEffect(AlphaISA::IPR_MM_STAT,
(((EV5::Opcode(tc->getInst()) & 0x3f) << 11)
| ((EV5::Ra(tc->getInst()) & 0x1f) << 6)
| (flags & 0x3f)));
tc->setMiscRegNoEffect(IPR_MM_STAT,
(((Opcode(tc->getInst()) & 0x3f) << 11) |
((Ra(tc->getInst()) & 0x1f) << 6) |
(flags & 0x3f)));
// set VA_FORM register with faulting formatted address
tc->setMiscRegNoEffect(AlphaISA::IPR_VA_FORM,
tc->readMiscRegNoEffect(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
tc->setMiscRegNoEffect(IPR_VA_FORM,
tc->readMiscRegNoEffect(IPR_MVPTBR) | (vaddr.vpn() << 3));
}
AlphaFault::invoke(tc);
}
void ItbFault::invoke(ThreadContext * tc)
void
ItbFault::invoke(ThreadContext *tc)
{
if (!tc->misspeculating()) {
tc->setMiscRegNoEffect(AlphaISA::IPR_ITB_TAG, pc);
tc->setMiscRegNoEffect(AlphaISA::IPR_IFAULT_VA_FORM,
tc->readMiscRegNoEffect(AlphaISA::IPR_IVPTBR) |
(AlphaISA::VAddr(pc).vpn() << 3));
tc->setMiscRegNoEffect(IPR_ITB_TAG, pc);
tc->setMiscRegNoEffect(IPR_IFAULT_VA_FORM,
tc->readMiscRegNoEffect(IPR_IVPTBR) | (VAddr(pc).vpn() << 3));
}
AlphaFault::invoke(tc);
@ -174,7 +176,8 @@ void ItbFault::invoke(ThreadContext * tc)
#else
void ItbPageFault::invoke(ThreadContext * tc)
void
ItbPageFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
TlbEntry entry;
@ -187,7 +190,8 @@ void ItbPageFault::invoke(ThreadContext * tc)
}
}
void NDtbMissFault::invoke(ThreadContext * tc)
void
NDtbMissFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
TlbEntry entry;

View file

@ -29,18 +29,16 @@
* Kevin Lim
*/
#ifndef __ALPHA_FAULTS_HH__
#define __ALPHA_FAULTS_HH__
#ifndef __ARCH_ALPHA_FAULTS_HH__
#define __ARCH_ALPHA_FAULTS_HH__
#include "arch/alpha/pagetable.hh"
#include "config/full_system.hh"
#include "sim/faults.hh"
#include "arch/alpha/pagetable.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh
namespace AlphaISA
{
namespace AlphaISA {
typedef const Addr FaultVect;
@ -63,6 +61,7 @@ class MachineCheckFault : public AlphaFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -76,6 +75,7 @@ class AlignmentFault : public AlphaFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -94,6 +94,7 @@ class ResetFault : public AlphaFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -102,12 +103,14 @@ class ResetFault : public AlphaFault
class ArithmeticFault : public AlphaFault
{
protected:
bool skipFaultingInstruction() {return true;}
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
protected:
bool skipFaultingInstruction() {return true;}
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -119,12 +122,14 @@ class ArithmeticFault : public AlphaFault
class InterruptFault : public AlphaFault
{
protected:
bool setRestartAddress() {return false;}
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
protected:
bool setRestartAddress() {return false;}
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -134,11 +139,12 @@ class InterruptFault : public AlphaFault
class DtbFault : public AlphaFault
{
protected:
AlphaISA::VAddr vaddr;
uint32_t reqFlags;
VAddr vaddr;
Request::Flags reqFlags;
uint64_t flags;
public:
DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags)
DtbFault(VAddr _vaddr, Request::Flags _reqFlags, uint64_t _flags)
: vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags)
{ }
FaultName name() const = 0;
@ -155,8 +161,9 @@ class NDtbMissFault : public DtbFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
NDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
FaultName name() const {return _name;}
@ -173,8 +180,9 @@ class PDtbMissFault : public DtbFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
PDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
FaultName name() const {return _name;}
@ -188,8 +196,9 @@ class DtbPageFault : public DtbFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
DtbPageFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
FaultName name() const {return _name;}
@ -203,8 +212,9 @@ class DtbAcvFault : public DtbFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
DtbAcvFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
FaultName name() const {return _name;}
@ -218,8 +228,9 @@ class DtbAlignmentFault : public DtbFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
DtbAlignmentFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
FaultName name() const {return _name;}
@ -231,10 +242,9 @@ class ItbFault : public AlphaFault
{
protected:
Addr pc;
public:
ItbFault(Addr _pc)
: pc(_pc)
{ }
ItbFault(Addr _pc) : pc(_pc) { }
FaultName name() const = 0;
FaultVect vect() = 0;
FaultStat & countStat() = 0;
@ -249,10 +259,9 @@ class ItbPageFault : public ItbFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
ItbPageFault(Addr pc)
: ItbFault(pc)
{ }
ItbPageFault(Addr pc) : ItbFault(pc) { }
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
@ -267,10 +276,9 @@ class ItbAcvFault : public ItbFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
ItbAcvFault(Addr pc)
: ItbFault(pc)
{ }
ItbAcvFault(Addr pc) : ItbFault(pc) { }
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
@ -282,6 +290,7 @@ class UnimplementedOpcodeFault : public AlphaFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -294,6 +303,7 @@ class FloatEnableFault : public AlphaFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -302,12 +312,14 @@ class FloatEnableFault : public AlphaFault
class PalFault : public AlphaFault
{
protected:
bool skipFaultingInstruction() {return true;}
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
protected:
bool skipFaultingInstruction() {return true;}
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
@ -320,12 +332,13 @@ class IntegerOverflowFault : public AlphaFault
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
FaultName name() const {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
} // AlphaISA namespace
} // namespace AlphaISA
#endif // __FAULTS_HH__
#endif // __ARCH_ALPHA_FAULTS_HH__

View file

@ -30,11 +30,18 @@
* Kevin Lim
*/
#include <cstring>
#include "arch/alpha/floatregfile.hh"
#include "sim/serialize.hh"
namespace AlphaISA
namespace AlphaISA {
void
FloatRegFile::clear()
{
std::memset(d, 0, sizeof(d));
}
void
FloatRegFile::serialize(std::ostream &os)
{
@ -46,4 +53,5 @@ namespace AlphaISA
{
UNSERIALIZE_ARRAY(q, NumFloatRegs);
}
}
} // namespace AlphaISA

View file

@ -32,37 +32,30 @@
#ifndef __ARCH_ALPHA_FLOATREGFILE_HH__
#define __ARCH_ALPHA_FLOATREGFILE_HH__
#include <iosfwd>
#include <string>
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/types.hh"
#include <cstring>
#include <iostream>
class Checkpoint;
namespace AlphaISA
{
static inline std::string getFloatRegName(RegIndex)
{
return "";
}
namespace AlphaISA {
class FloatRegFile
{
public:
union {
uint64_t q[NumFloatRegs]; // integer qword view
double d[NumFloatRegs]; // double-precision floating point view
};
void clear();
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
void clear()
{ std::memset(d, 0, sizeof(d)); }
};
}
#endif
} // namespace AlphaISA
#endif // __ARCH_ALPHA_FLOATREGFILE_HH__

View file

@ -62,29 +62,25 @@ FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p)
addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
}
FreebsdAlphaSystem::~FreebsdAlphaSystem()
{
delete skipDelayEvent;
delete skipCalibrateClocks;
}
void
FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc)
{
Addr ppc_vaddr = 0;
Addr timer_vaddr = 0;
assert(NumArgumentRegs >= 3);
ppc_vaddr = (Addr)tc->readIntReg(ArgumentReg[1]);
timer_vaddr = (Addr)tc->readIntReg(ArgumentReg[2]);
ppc_vaddr = (Addr)tc->readIntReg(17);
timer_vaddr = (Addr)tc->readIntReg(18);
virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency);
virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY);
}
void
FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ThreadContext *tc)
{

View file

@ -57,7 +57,6 @@ class FreebsdAlphaSystem : public AlphaSystem
~FreebsdAlphaSystem();
void doCalibrateClocks(ThreadContext *tc);
};
#endif // __ARCH_ALPHA_FREEBSD_SYSTEM_HH__

View file

@ -33,13 +33,14 @@
#include "arch/alpha/kernel_stats.hh"
#include "cpu/thread_context.hh"
using namespace TheISA;
using namespace AlphaISA;
void
IdleStartEvent::process(ThreadContext *tc)
{
if (tc->getKernelStats())
tc->getKernelStats()->setIdleProcess(
tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23), tc);
if (tc->getKernelStats()) {
MiscReg val = tc->readMiscRegNoEffect(IPR_PALtemp23);
tc->getKernelStats()->setIdleProcess(val, tc);
}
remove();
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* Copyright (c) 2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -28,8 +28,10 @@
* Authors: Gabe Black
*/
#include "cpu/o3/thread_context.hh"
#include "cpu/o3/thread_context_impl.hh"
template class O3ThreadContext<SparcSimpleImpl>;
#include "arch/alpha/interrupts.hh"
AlphaISA::Interrupts *
AlphaInterruptsParams::create()
{
return new AlphaISA::Interrupts(this);
}

View file

@ -35,46 +35,71 @@
#include "arch/alpha/faults.hh"
#include "arch/alpha/isa_traits.hh"
#include "base/compiler.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "params/AlphaInterrupts.hh"
#include "sim/sim_object.hh"
namespace AlphaISA
{
class Interrupts
namespace AlphaISA {
class Interrupts : public SimObject
{
private:
bool newInfoSet;
int newIpl;
int newSummary;
BaseCPU * cpu;
protected:
uint64_t interrupts[NumInterruptLevels];
uint64_t intstatus;
public:
Interrupts()
typedef AlphaInterruptsParams Params;
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
Interrupts(Params * p) : SimObject(p), cpu(NULL)
{
memset(interrupts, 0, sizeof(interrupts));
intstatus = 0;
newInfoSet = false;
}
void post(int int_num, int index)
void
setCPU(BaseCPU * _cpu)
{
cpu = _cpu;
}
void
post(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8)
if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
panic("int_num out of bounds\n");
interrupts[int_num] |= 1 << index;
intstatus |= (ULL(1) << int_num);
}
void clear(int int_num, int index)
void
clear(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8)
if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
panic("int_num out of bounds\n");
interrupts[int_num] &= ~(1 << index);
@ -82,7 +107,8 @@ namespace AlphaISA
intstatus &= ~(ULL(1) << int_num);
}
void clear_all()
void
clearAll()
{
DPRINTF(Interrupt, "Interrupts all cleared\n");
@ -90,24 +116,28 @@ namespace AlphaISA
intstatus = 0;
}
void serialize(std::ostream &os)
void
serialize(std::ostream &os)
{
SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
SERIALIZE_SCALAR(intstatus);
}
void unserialize(Checkpoint *cp, const std::string &section)
void
unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
UNSERIALIZE_SCALAR(intstatus);
}
bool check_interrupts(ThreadContext * tc) const
bool
checkInterrupts(ThreadContext *tc) const
{
return (intstatus != 0) && !(tc->readPC() & 0x3);
}
Fault getInterrupt(ThreadContext * tc)
Fault
getInterrupt(ThreadContext *tc)
{
int ipl = 0;
int summary = 0;
@ -151,26 +181,17 @@ namespace AlphaISA
}
}
void updateIntrInfo(ThreadContext *tc)
void
updateIntrInfo(ThreadContext *tc)
{
assert(newInfoSet);
tc->setMiscRegNoEffect(IPR_ISR, newSummary);
tc->setMiscRegNoEffect(IPR_INTID, newIpl);
newInfoSet = false;
}
uint64_t get_vec(int int_num)
{
panic("Shouldn't be called for Alpha\n");
M5_DUMMY_RETURN
}
private:
bool newInfoSet;
int newIpl;
int newSummary;
};
}
#endif
} // namespace AlphaISA
#endif // __ARCH_ALPHA_INTERRUPT_HH__

View file

@ -30,26 +30,34 @@
* Kevin Lim
*/
#include <cstring>
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/intregfile.hh"
#include "sim/serialize.hh"
namespace AlphaISA
{
namespace AlphaISA {
#if FULL_SYSTEM
const int reg_redir[AlphaISA::NumIntRegs] = {
const int reg_redir[NumIntRegs] = {
/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7,
/* 8 */ 32, 33, 34, 35, 36, 37, 38, 15,
/* 16 */ 16, 17, 18, 19, 20, 21, 22, 23,
/* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 };
#else
const int reg_redir[AlphaISA::NumIntRegs] = {
const int reg_redir[NumIntRegs] = {
/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7,
/* 8 */ 8, 9, 10, 11, 12, 13, 14, 15,
/* 16 */ 16, 17, 18, 19, 20, 21, 22, 23,
/* 24 */ 24, 25, 26, 27, 28, 29, 30, 31 };
#endif
void
IntRegFile::clear()
{
std::memset(regs, 0, sizeof(regs));
}
void
IntRegFile::serialize(std::ostream &os)
{
@ -61,5 +69,6 @@ namespace AlphaISA
{
UNSERIALIZE_ARRAY(regs, NumIntRegs);
}
}
} // namespace AlphaISA

View file

@ -32,19 +32,14 @@
#ifndef __ARCH_ALPHA_INTREGFILE_HH__
#define __ARCH_ALPHA_INTREGFILE_HH__
#include "arch/alpha/types.hh"
#include <iosfwd>
#include <string>
#include <iostream>
#include <cstring>
#include "arch/alpha/types.hh"
class Checkpoint;
namespace AlphaISA
{
static inline std::string getIntRegName(RegIndex)
{
return "";
}
namespace AlphaISA {
// redirected register map, really only used for the full system case.
extern const int reg_redir[NumIntRegs];
@ -55,24 +50,24 @@ namespace AlphaISA
IntReg regs[NumIntRegs];
public:
IntReg readReg(int intReg)
IntReg
readReg(int intReg)
{
return regs[intReg];
}
void setReg(int intReg, const IntReg &val)
void
setReg(int intReg, const IntReg &val)
{
regs[intReg] = val;
}
void clear();
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
void clear()
{ std::memset(regs, 0, sizeof(regs)); }
};
}
#endif
} // namespace AlphaISA
#endif // __ARCH_ALPHA_INTREGFILE_HH__

View file

@ -28,15 +28,15 @@
* Authors: Gabe Black
*/
#include <assert.h>
#include <string.h>
#include <cassert>
#include <cstring>
#include "arch/alpha/ipr.hh"
namespace AlphaISA
{
md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] =
{
namespace AlphaISA {
md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] = {
//Write only
RAW_IPR_HWINT_CLR, // H/W interrupt clear register
RAW_IPR_SL_XMIT, // serial line transmit register
@ -125,7 +125,8 @@ namespace AlphaISA
int IprToMiscRegIndex[MaxInternalProcRegs];
void initializeIprTable()
void
initializeIprTable()
{
static bool initialized = false;
if (initialized)
@ -136,5 +137,6 @@ namespace AlphaISA
for (int x = 0; x < NumInternalProcRegs; x++)
IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x;
}
}
} // namespace AlphaISA

View file

@ -32,41 +32,40 @@
#ifndef __ARCH_ALPHA_IPR_HH__
#define __ARCH_ALPHA_IPR_HH__
namespace AlphaISA
{
namespace AlphaISA {
////////////////////////////////////////////////////////////////////////
//
// Internal Processor Reigsters
//
enum md_ipr_names
{
RAW_IPR_ISR = 0x100, // interrupt summary register
RAW_IPR_ITB_TAG = 0x101, // ITLB tag register
RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry register
RAW_IPR_ITB_ASN = 0x103, // ITLB address space register
RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register
RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all register
RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process register
RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select register
RAW_IPR_SIRR = 0x108, // software interrupt request register
RAW_IPR_ASTRR = 0x109, // asynchronous system trap request register
RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable register
RAW_IPR_EXC_ADDR = 0x10b, // exception address register
RAW_IPR_EXC_SUM = 0x10c, // exception summary register
RAW_IPR_EXC_MASK = 0x10d, // exception mask register
RAW_IPR_PAL_BASE = 0x10e, // PAL base address register
enum md_ipr_names {
RAW_IPR_ISR = 0x100, // interrupt summary
RAW_IPR_ITB_TAG = 0x101, // ITLB tag
RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry
RAW_IPR_ITB_ASN = 0x103, // ITLB address space
RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp
RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all
RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process
RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select
RAW_IPR_SIRR = 0x108, // software interrupt request
RAW_IPR_ASTRR = 0x109, // asynchronous system trap request
RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable
RAW_IPR_EXC_ADDR = 0x10b, // exception address
RAW_IPR_EXC_SUM = 0x10c, // exception summary
RAW_IPR_EXC_MASK = 0x10d, // exception mask
RAW_IPR_PAL_BASE = 0x10e, // PAL base address
RAW_IPR_ICM = 0x10f, // instruction current mode
RAW_IPR_IPLR = 0x110, // interrupt priority level register
RAW_IPR_INTID = 0x111, // interrupt ID register
RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register
RAW_IPR_IVPTBR = 0x113, // virtual page table base register
RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear register
RAW_IPR_SL_XMIT = 0x116, // serial line transmit register
RAW_IPR_SL_RCV = 0x117, // serial line receive register
RAW_IPR_ICSR = 0x118, // instruction control and status register
RAW_IPR_IPLR = 0x110, // interrupt priority level
RAW_IPR_INTID = 0x111, // interrupt ID
RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr
RAW_IPR_IVPTBR = 0x113, // virtual page table base
RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear
RAW_IPR_SL_XMIT = 0x116, // serial line transmit
RAW_IPR_SL_RCV = 0x117, // serial line receive
RAW_IPR_ICSR = 0x118, // instruction control and status
RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control
RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register
RAW_IPR_PMCTR = 0x11c, // performance counter register
RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status
RAW_IPR_PMCTR = 0x11c, // performance counter
// PAL temporary registers...
// register meanings gleaned from osfpal.s source code
@ -95,33 +94,33 @@ namespace AlphaISA
RAW_IPR_PALtemp22 = 0x156, // kgp
RAW_IPR_PALtemp23 = 0x157, // PCBB
RAW_IPR_DTB_ASN = 0x200, // DTLB address space number register
RAW_IPR_DTB_CM = 0x201, // DTLB current mode register
RAW_IPR_DTB_TAG = 0x202, // DTLB tag register
RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry register
RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register
RAW_IPR_DTB_ASN = 0x200, // DTLB address space number
RAW_IPR_DTB_CM = 0x201, // DTLB current mode
RAW_IPR_DTB_TAG = 0x202, // DTLB tag
RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry
RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary
RAW_IPR_MM_STAT = 0x205, // data MMU fault status register
RAW_IPR_VA = 0x206, // fault virtual address register
RAW_IPR_VA_FORM = 0x207, // formatted virtual address register
RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base register
RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process register
RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all register
RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single register
RAW_IPR_ALT_MODE = 0x20c, // alternate mode register
RAW_IPR_CC = 0x20d, // cycle counter register
RAW_IPR_CC_CTL = 0x20e, // cycle counter control register
RAW_IPR_MCSR = 0x20f, // MTU control register
RAW_IPR_MM_STAT = 0x205, // data MMU fault status
RAW_IPR_VA = 0x206, // fault virtual address
RAW_IPR_VA_FORM = 0x207, // formatted virtual address
RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base
RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process
RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all
RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single
RAW_IPR_ALT_MODE = 0x20c, // alternate mode
RAW_IPR_CC = 0x20d, // cycle counter
RAW_IPR_CC_CTL = 0x20e, // cycle counter control
RAW_IPR_MCSR = 0x20f, // MTU control
RAW_IPR_DC_FLUSH = 0x210,
RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register
RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register
RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag register
RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register
RAW_IPR_DC_MODE = 0x216, // Dcache mode register
RAW_IPR_MAF_MODE = 0x217, // miss address file mode register
RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status
RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control
RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag
RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary
RAW_IPR_DC_MODE = 0x216, // Dcache mode
RAW_IPR_MAF_MODE = 0x217, // miss address file mode
MaxInternalProcRegs // number of IPR registers
MaxInternalProcRegs // number of IPRs
};
enum MiscRegIpr
@ -218,12 +217,14 @@ namespace AlphaISA
NumInternalProcRegs // number of IPR registers
};
inline bool IprIsWritable(int index)
inline bool
IprIsWritable(int index)
{
return index < MinReadOnlyIpr || index > MaxReadOnlyIpr;
}
inline bool IprIsReadable(int index)
inline bool
IprIsReadable(int index)
{
return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr;
}
@ -232,6 +233,7 @@ namespace AlphaISA
extern int IprToMiscRegIndex[MaxInternalProcRegs];
void initializeIprTable();
}
#endif
} // namespace AlphaISA
#endif // __ARCH_ALPHA_IPR_HH__

View file

@ -638,7 +638,7 @@ decode OPCODE default Unknown::unknown() {
/* Rb is a fake dependency so here is a fun way to get
* the parser to understand that.
*/
Ra = xc->readMiscReg(AlphaISA::IPR_CC) + (Rb & 0);
Ra = xc->readMiscReg(IPR_CC) + (Rb & 0);
#else
Ra = curTick;
@ -690,7 +690,7 @@ decode OPCODE default Unknown::unknown() {
0x00: CallPal::call_pal({{
if (!palValid ||
(palPriv
&& xc->readMiscReg(AlphaISA::IPR_ICM) != AlphaISA::mode_kernel)) {
&& xc->readMiscReg(IPR_ICM) != mode_kernel)) {
// invalid pal function code, or attempt to do privileged
// PAL call in non-kernel mode
fault = new UnimplementedOpcodeFault;
@ -701,8 +701,8 @@ decode OPCODE default Unknown::unknown() {
bool dopal = xc->simPalCheck(palFunc);
if (dopal) {
xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, NPC);
NPC = xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + palOffset;
xc->setMiscReg(IPR_EXC_ADDR, NPC);
NPC = xc->readMiscReg(IPR_PAL_BASE) + palOffset;
}
}
}}, IsNonSpeculative);
@ -783,14 +783,19 @@ decode OPCODE default Unknown::unknown() {
}
}
format BasicOperate {
0x1e: decode PALMODE {
0: OpcdecFault::hw_rei();
format BasicOperate {
1: hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore);
}
}
#endif
format BasicOperate {
// M5 special opcodes use the reserved 0x01 opcode space
0x01: decode M5FUNC {
#if FULL_SYSTEM
0x00: arm({{
PseudoInst::arm(xc->tcBase());
}}, IsNonSpeculative);
@ -806,22 +811,34 @@ decode OPCODE default Unknown::unknown() {
0x04: quiesceTime({{
R0 = PseudoInst::quiesceTime(xc->tcBase());
}}, IsNonSpeculative, IsUnverifiable);
0x10: ivlb({{
warn_once("Obsolete M5 instruction ivlb encountered.\n");
#endif
0x07: rpns({{
R0 = PseudoInst::rpns(xc->tcBase());
}}, IsNonSpeculative, IsUnverifiable);
0x09: wakeCPU({{
PseudoInst::wakeCPU(xc->tcBase(), R16);
}}, IsNonSpeculative, IsUnverifiable);
0x10: deprecated_ivlb({{
warn_once("Obsolete M5 ivlb instruction encountered.\n");
}});
0x11: ivle({{
warn_once("Obsolete M5 instruction ivlb encountered.\n");
0x11: deprecated_ivle({{
warn_once("Obsolete M5 ivlb instruction encountered.\n");
}});
0x20: m5exit_old({{
PseudoInst::m5exit_old(xc->tcBase());
0x20: deprecated_exit ({{
warn_once("deprecated M5 exit instruction encountered.\n");
PseudoInst::m5exit(xc->tcBase(), 0);
}}, No_OpClass, IsNonSpeculative);
0x21: m5exit({{
PseudoInst::m5exit(xc->tcBase(), R16);
}}, No_OpClass, IsNonSpeculative);
#if FULL_SYSTEM
0x31: loadsymbol({{
PseudoInst::loadsymbol(xc->tcBase());
}}, No_OpClass, IsNonSpeculative);
0x30: initparam({{ Ra = xc->tcBase()->getCpuPtr()->system->init_param; }});
0x30: initparam({{
Ra = xc->tcBase()->getCpuPtr()->system->init_param;
}});
#endif
0x40: resetstats({{
PseudoInst::resetstats(xc->tcBase(), R16, R17);
}}, IsNonSpeculative);
@ -834,28 +851,93 @@ decode OPCODE default Unknown::unknown() {
0x43: m5checkpoint({{
PseudoInst::m5checkpoint(xc->tcBase(), R16, R17);
}}, IsNonSpeculative);
#if FULL_SYSTEM
0x50: m5readfile({{
R0 = PseudoInst::readfile(xc->tcBase(), R16, R17, R18);
}}, IsNonSpeculative);
#endif
0x51: m5break({{
PseudoInst::debugbreak(xc->tcBase());
}}, IsNonSpeculative);
0x52: m5switchcpu({{
PseudoInst::switchcpu(xc->tcBase());
}}, IsNonSpeculative);
#if FULL_SYSTEM
0x53: m5addsymbol({{
PseudoInst::addsymbol(xc->tcBase(), R16, R17);
}}, IsNonSpeculative);
#endif
0x54: m5panic({{
panic("M5 panic instruction called at pc=%#x.", xc->readPC());
}}, IsNonSpeculative);
0x55: m5anBegin({{
PseudoInst::anBegin(xc->tcBase(), R16);
#define CPANN(lbl) CPA::cpa()->lbl(xc->tcBase())
0x55: decode RA {
0x00: m5a_old({{
panic("Deprecated M5 annotate instruction executed at pc=%#x\n",
xc->readPC());
}}, IsNonSpeculative);
0x56: m5anWait({{
PseudoInst::anWait(xc->tcBase(), R16, R17);
0x01: m5a_bsm({{
CPANN(swSmBegin);
}}, IsNonSpeculative);
0x02: m5a_esm({{
CPANN(swSmEnd);
}}, IsNonSpeculative);
0x03: m5a_begin({{
CPANN(swExplictBegin);
}}, IsNonSpeculative);
0x04: m5a_end({{
CPANN(swEnd);
}}, IsNonSpeculative);
0x06: m5a_q({{
CPANN(swQ);
}}, IsNonSpeculative);
0x07: m5a_dq({{
CPANN(swDq);
}}, IsNonSpeculative);
0x08: m5a_wf({{
CPANN(swWf);
}}, IsNonSpeculative);
0x09: m5a_we({{
CPANN(swWe);
}}, IsNonSpeculative);
0x0C: m5a_sq({{
CPANN(swSq);
}}, IsNonSpeculative);
0x0D: m5a_aq({{
CPANN(swAq);
}}, IsNonSpeculative);
0x0E: m5a_pq({{
CPANN(swPq);
}}, IsNonSpeculative);
0x0F: m5a_l({{
CPANN(swLink);
}}, IsNonSpeculative);
0x10: m5a_identify({{
CPANN(swIdentify);
}}, IsNonSpeculative);
0x11: m5a_getid({{
R0 = CPANN(swGetId);
}}, IsNonSpeculative);
0x13: m5a_scl({{
CPANN(swSyscallLink);
}}, IsNonSpeculative);
0x14: m5a_rq({{
CPANN(swRq);
}}, IsNonSpeculative);
} // M5 Annotate Operations
#undef CPANN
0x56: m5reserved2({{
warn("M5 reserved opcode ignored");
}}, IsNonSpeculative);
0x57: m5reserved3({{
warn("M5 reserved opcode ignored");
}}, IsNonSpeculative);
0x58: m5reserved4({{
warn("M5 reserved opcode ignored");
}}, IsNonSpeculative);
0x59: m5reserved5({{
warn("M5 reserved opcode ignored");
}}, IsNonSpeculative);
}
}
#endif
}

View file

@ -46,7 +46,7 @@ output exec {{
inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
{
Fault fault = NoFault; // dummy... this ipr access should not fault
if (!EV5::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) {
if (!ICSR_FPE(xc->readMiscReg(IPR_ICSR))) {
fault = new FloatEnableFault;
}
return fault;
@ -229,7 +229,7 @@ def template FloatingPointExecute {{
%(code)s;
} else {
m5_fesetround(getC99RoundingMode(
xc->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR)));
xc->readMiscRegNoEffect(MISCREG_FPCR)));
%(code)s;
m5_fesetround(M5_FE_TONEAREST);
}

View file

@ -68,9 +68,8 @@ using namespace AlphaISA;
output exec {{
#include <math.h>
#if FULL_SYSTEM
#include "base/cp_annotate.hh"
#include "sim/pseudo_inst.hh"
#endif
#include "arch/alpha/ipr.hh"
#include "base/fenv.hh"
#include "config/ss_compatible_fp.hh"
@ -173,11 +172,11 @@ def operands {{
# Int regs default to unsigned, but code should not count on this.
# For clarity, descriptions that depend on unsigned behavior should
# explicitly specify '.uq'.
'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA',
'Ra': ('IntReg', 'uq', 'PALMODE ? reg_redir[RA] : RA',
'IsInteger', 1),
'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB',
'Rb': ('IntReg', 'uq', 'PALMODE ? reg_redir[RB] : RB',
'IsInteger', 2),
'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC',
'Rc': ('IntReg', 'uq', 'PALMODE ? reg_redir[RC] : RC',
'IsInteger', 3),
'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),

View file

@ -43,7 +43,7 @@ output header {{
protected:
/// Memory request flags. See mem_req_base.hh.
unsigned memAccessFlags;
Request::Flags memAccessFlags;
/// Pointer to EAComp object.
const StaticInstPtr eaCompPtr;
/// Pointer to MemAcc object.
@ -54,7 +54,7 @@ output header {{
StaticInstPtr _eaCompPtr = nullStaticInstPtr,
StaticInstPtr _memAccPtr = nullStaticInstPtr)
: AlphaStaticInst(mnem, _machInst, __opClass),
memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
{
}
@ -677,6 +677,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
inst_flags)
if mem_flags:
mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
iop.constructor += s
memacc_iop.constructor += s

View file

@ -174,11 +174,11 @@ output decoder {{
: Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
disp(HW_LDST_DISP)
{
memAccessFlags = 0;
if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
if (HW_LDST_VPTE) memAccessFlags |= VPTE;
if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
memAccessFlags.clear();
if (HW_LDST_PHYS) memAccessFlags.set(Request::PHYSICAL);
if (HW_LDST_ALT) memAccessFlags.set(Request::ALTMODE);
if (HW_LDST_VPTE) memAccessFlags.set(Request::VPTE);
if (HW_LDST_LOCK) memAccessFlags.set(Request::LOCKED);
}
std::string

View file

@ -42,8 +42,8 @@ namespace LittleEndianGuest {}
class StaticInstPtr;
namespace AlphaISA
{
namespace AlphaISA {
using namespace LittleEndianGuest;
using AlphaISAInst::MaxInstSrcRegs;
using AlphaISAInst::MaxInstDestRegs;
@ -66,7 +66,6 @@ namespace AlphaISA
const Addr PageMask = ~(PageBytes - 1);
const Addr PageOffset = PageBytes - 1;
////////////////////////////////////////////////////////////////////////
//
// Translation stuff
@ -92,8 +91,6 @@ namespace AlphaISA
// For loading... XXX This maybe could be USegEnd?? --ali
const Addr LoadAddrMask = ULL(0xffffffffff);
#if FULL_SYSTEM
////////////////////////////////////////////////////////////////////////
//
// Interrupt levels
@ -118,8 +115,6 @@ namespace AlphaISA
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
};
#endif
// EV5 modes
enum mode_type
{
@ -142,8 +137,8 @@ namespace AlphaISA
const int NumFloatRegs = NumFloatArchRegs;
const int NumMiscRegs = NumMiscArchRegs;
const int TotalNumRegs = NumIntRegs + NumFloatRegs +
NumMiscRegs + NumInternalProcRegs;
const int TotalNumRegs =
NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs;
const int TotalDataRegs = NumIntRegs + NumFloatRegs;
@ -157,12 +152,9 @@ namespace AlphaISA
const int ReturnValueReg = 0;
const int FramePointerReg = 15;
const int ArgumentReg[] = {16, 17, 18, 19, 20, 21};
const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int);
const int SyscallNumReg = ReturnValueReg;
const int SyscallPseudoReturnReg = ArgumentReg[4];
const int SyscallSuccessReg = 19;
const int SyscallNumReg = 0;
const int FirstArgumentReg = 16;
const int SyscallPseudoReturnReg = 20;
const int LogVMPageSize = 13; // 8K bytes
const int VMPageSize = (1 << LogVMPageSize);
@ -178,6 +170,6 @@ namespace AlphaISA
// Alpha UNOP (ldq_u r31,0(r0))
const ExtMachInst NoopMachInst = 0x2ffe0000;
};
} // namespace AlphaISA
#endif // __ARCH_ALPHA_ISA_TRAITS_HH__

View file

@ -152,7 +152,7 @@ Statistics::changeMode(cpu_mode newmode, ThreadContext *tc)
void
Statistics::mode(cpu_mode newmode, ThreadContext *tc)
{
Addr pcbb = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23);
Addr pcbb = tc->readMiscRegNoEffect(IPR_PALtemp23);
if (newmode == kernel && pcbb == idleProcess)
newmode = idle;
@ -213,5 +213,5 @@ Statistics::unserialize(Checkpoint *cp, const string &section)
themode = (cpu_mode)exemode;
}
} /* end namespace AlphaISA::Kernel */
} /* end namespace AlphaISA */
} // namespace Kernel
} // namespace AlphaISA

View file

@ -62,15 +62,15 @@ class Statistics : public ::Kernel::Statistics
void changeMode(cpu_mode newmode, ThreadContext *tc);
private:
Stats::Vector<> _callpal;
// Stats::Vector<> _faults;
Stats::Vector _callpal;
// Stats::Vector _faults;
Stats::Vector<> _mode;
Stats::Vector<> _modeGood;
Stats::Vector _mode;
Stats::Vector _modeGood;
Stats::Formula _modeFraction;
Stats::Vector<> _modeTicks;
Stats::Vector _modeTicks;
Stats::Scalar<> _swap_context;
Stats::Scalar _swap_context;
public:
Statistics(System *system);
@ -90,7 +90,7 @@ class Statistics : public ::Kernel::Statistics
void unserialize(Checkpoint *cp, const std::string &section);
};
} /* end namespace AlphaISA::Kernel */
} /* end namespace AlphaISA */
} // namespace Kernel
} // namespace AlphaISA
#endif // __ARCH_ALPHA_KERNEL_STATS_HH__

View file

@ -28,10 +28,10 @@
* Authors: Korey Sewell
*/
#include "arch/alpha/linux/linux.hh"
#include <fcntl.h>
#include "arch/alpha/linux/linux.hh"
// open(2) flags translation table
OpenFlagTransTable AlphaLinux::openFlagTable[] = {
#ifdef _MSC_VER
@ -69,6 +69,3 @@ OpenFlagTransTable AlphaLinux::openFlagTable[] = {
const int AlphaLinux::NUM_OPEN_FLAGS =
(sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0]));

View file

@ -28,8 +28,8 @@
* Authors: Korey Sewell
*/
#ifndef __ALPHA_ALPHA_LINUX_HH
#define __ALPHA_ALPHA_LINUX_HH
#ifndef __ALPHA_ALPHA_LINUX_LINUX_HH__
#define __ALPHA_ALPHA_LINUX_LINUX_HH__
#include "kern/linux/linux.hh"
@ -75,7 +75,7 @@ class AlphaLinux : public Linux
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
static const unsigned GSI_CPU_INFO = 59; //!< CPU information
static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine
static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
@ -127,4 +127,4 @@ class AlphaLinux : public Linux
};
};
#endif
#endif // __ALPHA_ALPHA_LINUX_LINUX_HH__

View file

@ -43,18 +43,16 @@
using namespace std;
using namespace AlphaISA;
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0));
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
strcpy(name->sysname, "Linux");
strcpy(name->nodename, "m5.eecs.umich.edu");
strcpy(name->release, "2.4.20");
strcpy(name->release, "2.6.26");
strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
strcpy(name->machine, "alpha");
@ -69,13 +67,13 @@ static SyscallReturn
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = tc->getSyscallArg(0);
// unsigned nbytes = tc->getSyscallArg(2);
unsigned op = process->getSyscallArg(tc, 0);
// unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) {
case 45: { // GSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(tc->getSyscallArg(1));
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
// I don't think this exactly matches the HW FPCR
*fpcr = 0;
fpcr.copyOut(tc->getMemPort());
@ -96,13 +94,13 @@ static SyscallReturn
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = tc->getSyscallArg(0);
// unsigned nbytes = tc->getSyscallArg(2);
unsigned op = process->getSyscallArg(tc, 0);
// unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) {
case 14: { // SSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(tc->getSyscallArg(1));
TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
// I don't think this exactly matches the HW FPCR
fpcr.copyIn(tc->getMemPort());
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
@ -138,7 +136,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 14 */ SyscallDesc("mknod", unimplementedFunc),
/* 15 */ SyscallDesc("chmod", chmodFunc<AlphaLinux>),
/* 16 */ SyscallDesc("chown", chownFunc),
/* 17 */ SyscallDesc("brk", obreakFunc),
/* 17 */ SyscallDesc("brk", brkFunc),
/* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", lseekFunc),
/* 20 */ SyscallDesc("getxpid", getpidPseudoFunc),
@ -179,9 +177,9 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 55 */ SyscallDesc("osf_reboot", unimplementedFunc),
/* 56 */ SyscallDesc("osf_revoke", unimplementedFunc),
/* 57 */ SyscallDesc("symlink", unimplementedFunc),
/* 58 */ SyscallDesc("readlink", unimplementedFunc),
/* 58 */ SyscallDesc("readlink", readlinkFunc),
/* 59 */ SyscallDesc("execve", unimplementedFunc),
/* 60 */ SyscallDesc("umask", unimplementedFunc),
/* 60 */ SyscallDesc("umask", umaskFunc),
/* 61 */ SyscallDesc("chroot", unimplementedFunc),
/* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc),
/* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
@ -250,14 +248,14 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 126 */ SyscallDesc("setreuid", unimplementedFunc),
/* 127 */ SyscallDesc("setregid", unimplementedFunc),
/* 128 */ SyscallDesc("rename", renameFunc),
/* 129 */ SyscallDesc("truncate", unimplementedFunc),
/* 130 */ SyscallDesc("ftruncate", unimplementedFunc),
/* 129 */ SyscallDesc("truncate", truncateFunc),
/* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
/* 131 */ SyscallDesc("flock", unimplementedFunc),
/* 132 */ SyscallDesc("setgid", unimplementedFunc),
/* 133 */ SyscallDesc("sendto", unimplementedFunc),
/* 134 */ SyscallDesc("shutdown", unimplementedFunc),
/* 135 */ SyscallDesc("socketpair", unimplementedFunc),
/* 136 */ SyscallDesc("mkdir", unimplementedFunc),
/* 136 */ SyscallDesc("mkdir", mkdirFunc),
/* 137 */ SyscallDesc("rmdir", unimplementedFunc),
/* 138 */ SyscallDesc("osf_utimes", unimplementedFunc),
/* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc),
@ -465,7 +463,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 338 */ SyscallDesc("afs_syscall", unimplementedFunc),
/* 339 */ SyscallDesc("uname", unameFunc),
/* 340 */ SyscallDesc("nanosleep", unimplementedFunc),
/* 341 */ SyscallDesc("mremap", unimplementedFunc),
/* 341 */ SyscallDesc("mremap", mremapFunc<AlphaLinux>),
/* 342 */ SyscallDesc("nfsservctl", unimplementedFunc),
/* 343 */ SyscallDesc("setresuid", unimplementedFunc),
/* 344 */ SyscallDesc("getresuid", unimplementedFunc),
@ -491,7 +489,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 364 */ SyscallDesc("getrusage", getrusageFunc<AlphaLinux>),
/* 365 */ SyscallDesc("wait4", unimplementedFunc),
/* 366 */ SyscallDesc("adjtimex", unimplementedFunc),
/* 367 */ SyscallDesc("getcwd", unimplementedFunc),
/* 367 */ SyscallDesc("getcwd", getcwdFunc),
/* 368 */ SyscallDesc("capget", unimplementedFunc),
/* 369 */ SyscallDesc("capset", unimplementedFunc),
/* 370 */ SyscallDesc("sendfile", unimplementedFunc),
@ -581,7 +579,7 @@ AlphaLinuxProcess::AlphaLinuxProcess(LiveProcessParams * params,
SyscallDesc*
AlphaLinuxProcess::getDesc(int callnum)
{
if (callnum < 0 || callnum > Num_Syscall_Descs)
if (callnum < 0 || callnum >= Num_Syscall_Descs)
return NULL;
return &syscallDescs[callnum];
}

View file

@ -51,4 +51,5 @@ class AlphaLinuxProcess : public AlphaLiveProcess
};
} // namespace AlphaISA
#endif // __ALPHA_LINUX_PROCESS_HH__

View file

@ -157,7 +157,6 @@ LinuxAlphaSystem::~LinuxAlphaSystem()
delete printThreadEvent;
}
void
LinuxAlphaSystem::setDelayLoop(ThreadContext *tc)
{
@ -169,11 +168,9 @@ LinuxAlphaSystem::setDelayLoop(ThreadContext *tc)
vp = tc->getVirtPort();
vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988));
tc->delVirtPort(vp);
}
}
void
LinuxAlphaSystem::SkipDelayLoopEvent::process(ThreadContext *tc)
{

View file

@ -43,9 +43,6 @@ class IdleStartEvent;
#include "kern/linux/events.hh"
#include "params/LinuxAlphaSystem.hh"
using namespace AlphaISA;
using namespace Linux;
/**
* This class contains linux specific system code (Loading, Events).
* It points to objects that are the system binaries to load and patches them
@ -54,23 +51,20 @@ using namespace Linux;
class LinuxAlphaSystem : public AlphaSystem
{
private:
class SkipDelayLoopEvent : public SkipFuncEvent
struct SkipDelayLoopEvent : public SkipFuncEvent
{
public:
SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr)
: SkipFuncEvent(q, desc, addr) {}
virtual void process(ThreadContext *tc);
};
class PrintThreadInfo : public PCEvent
struct PrintThreadInfo : public PCEvent
{
public:
PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr)
: PCEvent(q, desc, addr) {}
virtual void process(ThreadContext *tc);
};
/**
* Addresses defining where the kernel bootloader places various
* elements. Details found in include/asm-alpha/system.h
@ -112,7 +106,7 @@ class LinuxAlphaSystem : public AlphaSystem
* PC based event to skip the dprink() call and emulate its
* functionality
*/
DebugPrintkEvent *debugPrintkEvent;
Linux::DebugPrintkEvent *debugPrintkEvent;
/**
* Skip calculate_delay_loop() rather than waiting for this to be

View file

@ -55,7 +55,7 @@ class ThreadInfo
CopyOut(tc, &data, addr, sizeof(T));
data = TheISA::gtoh(data);
data = AlphaISA::gtoh(data);
return true;
}
@ -76,7 +76,7 @@ class ThreadInfo
Addr sp;
if (!addr)
addr = tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23);
addr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23);
FunctionalPort *p = tc->getPhysPort();
p->readBlob(addr, (uint8_t *)&sp, sizeof(Addr));
@ -147,6 +147,6 @@ class ThreadInfo
}
};
/* namespace Linux */ }
} // namespace Linux
#endif // __ARCH_ALPHA_LINUX_LINUX_THREADINFO_HH__

View file

@ -49,9 +49,8 @@
#include "base/misc.hh"
#include "mem/request.hh"
namespace AlphaISA {
namespace AlphaISA
{
template <class XC>
inline void
handleLockedRead(XC *xc, Request *req)
@ -86,9 +85,9 @@ handleLockedWrite(XC *xc, Request *req)
stCondFailures++;
xc->setStCondFailures(stCondFailures);
if (stCondFailures % 100000 == 0) {
warn("cpu %d: %d consecutive "
warn("context %d: %d consecutive "
"store conditional failures\n",
xc->readCpuId(), stCondFailures);
xc->contextId(), stCondFailures);
}
// store conditional failed already, so don't issue it to mem
@ -99,7 +98,6 @@ handleLockedWrite(XC *xc, Request *req)
return true;
}
} // namespace AlphaISA
#endif
#endif // __ARCH_ALPHA_LOCKED_MEM_HH__

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#ifndef __ARCH_ALPHA_MICROCODE_ROM_HH__
#define __ARCH_ALPHA_MICROCODE_ROM_HH__
#include "sim/microcode_rom.hh"
namespace AlphaISA
{
using ::MicrocodeRom;
}
#endif // __ARCH_ALPHA_MICROCODE_ROM_HH__

View file

@ -30,11 +30,12 @@
* Kevin Lim
*/
#include <cassert>
#include "arch/alpha/miscregfile.hh"
#include "base/misc.hh"
namespace AlphaISA
{
namespace AlphaISA {
void
MiscRegFile::serialize(std::ostream &os)
@ -122,8 +123,7 @@ namespace AlphaISA
}
void
MiscRegFile::setReg(int misc_reg, const MiscReg &val,
ThreadContext *tc)
MiscRegFile::setReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
{
switch (misc_reg) {
case MISCREG_FPCR:
@ -147,4 +147,4 @@ namespace AlphaISA
}
}
}
} // namespace AlphaISA

View file

@ -32,18 +32,18 @@
#ifndef __ARCH_ALPHA_MISCREGFILE_HH__
#define __ARCH_ALPHA_MISCREGFILE_HH__
#include <iosfwd>
#include "arch/alpha/ipr.hh"
#include "arch/alpha/types.hh"
#include "sim/host.hh"
#include "sim/serialize.hh"
#include <iostream>
class Checkpoint;
class ThreadContext;
namespace AlphaISA
{
namespace AlphaISA {
enum MiscRegIndex
{
MISCREG_FPCR = NumInternalProcRegs,
@ -53,12 +53,12 @@ namespace AlphaISA
MISCREG_INTR
};
static inline std::string getMiscRegName(RegIndex)
class MiscRegFile
{
return "";
}
public:
friend class RegFile;
typedef uint64_t InternalProcReg;
class MiscRegFile {
protected:
uint64_t fpcr; // floating point condition codes
uint64_t uniq; // process-unique register
@ -66,51 +66,45 @@ namespace AlphaISA
Addr lock_addr; // lock address for LL/SC
int intr_flag;
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
protected:
InternalProcReg readIpr(int idx, ThreadContext *tc);
void setIpr(int idx, InternalProcReg val, ThreadContext *tc);
public:
MiscRegFile()
{
initializeIprTable();
}
MiscReg readRegNoEffect(int misc_reg);
MiscReg readReg(int misc_reg, ThreadContext *tc);
//These functions should be removed once the simplescalar cpu model
//has been replaced.
// These functions should be removed once the simplescalar cpu
// model has been replaced.
int getInstAsid();
int getDataAsid();
MiscReg readRegNoEffect(int misc_reg);
MiscReg readReg(int misc_reg, ThreadContext *tc);
void setRegNoEffect(int misc_reg, const MiscReg &val);
void setReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
void setReg(int misc_reg, const MiscReg &val,
ThreadContext *tc);
void clear()
void
clear()
{
fpcr = uniq = 0;
fpcr = 0;
uniq = 0;
lock_flag = 0;
lock_addr = 0;
intr_flag = 0;
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
protected:
typedef uint64_t InternalProcReg;
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
private:
InternalProcReg readIpr(int idx, ThreadContext *tc);
void setIpr(int idx, InternalProcReg val, ThreadContext *tc);
friend class RegFile;
};
void copyIprs(ThreadContext *src, ThreadContext *dest);
}
} // namespace AlphaISA
#endif
#endif // __ARCH_ALPHA_MISCREGFILE_HH__

View file

@ -39,9 +39,8 @@
#include "mem/packet.hh"
namespace AlphaISA {
namespace AlphaISA
{
inline Tick
handleIprRead(ThreadContext *xc, Packet *pkt)
{
@ -58,4 +57,4 @@ handleIprWrite(ThreadContext *xc, Packet *pkt)
} // namespace AlphaISA
#endif
#endif // __ARCH_ALPHA_MMAPED_IPR_HH__

View file

@ -30,8 +30,10 @@
#include "arch/alpha/osfpal.hh"
namespace {
const char *strings[PAL::NumCodes] = {
const char *
PAL::name(int index)
{
static const char *strings[PAL::NumCodes] = {
// Priviledged PAL instructions
"halt", // 0x00
"cflush", // 0x01
@ -294,11 +296,7 @@ namespace {
0 // 0xff
#endif
};
}
const char *
PAL::name(int index)
{
if (index > NumCodes || index < 0)
return 0;

View file

@ -28,8 +28,8 @@
* Authors: Nathan Binkert
*/
#ifndef __OSFPAL_HH__
#define __OSFPAL_HH__
#ifndef __ARCH_ALPHA_OSFPAL_HH__
#define __ARCH_ALPHA_OSFPAL_HH__
struct PAL
{
@ -79,4 +79,4 @@ struct PAL
static const char *name(int index);
};
#endif // __OSFPAL_HH__
#endif // __ARCH_ALPHA_OSFPAL_HH__

View file

@ -31,8 +31,8 @@
#include "arch/alpha/pagetable.hh"
#include "sim/serialize.hh"
namespace AlphaISA
{
namespace AlphaISA {
void
TlbEntry::serialize(std::ostream &os)
{
@ -60,4 +60,5 @@ namespace AlphaISA
UNSERIALIZE_SCALAR(fonw);
UNSERIALIZE_SCALAR(valid);
}
}
} //namespace AlphaISA

View file

@ -44,8 +44,9 @@ namespace AlphaISA {
static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
static const Addr UnImplMask = ~ImplMask;
VAddr(Addr a) : addr(a) {}
Addr addr;
VAddr(Addr a) : addr(a) {}
operator Addr() const { return addr; }
const VAddr &operator=(Addr a) { addr = a; return *this; }
@ -54,11 +55,11 @@ namespace AlphaISA {
Addr offset() const { return addr & PageOffset; }
Addr level3() const
{ return AlphaISA::PteAddr(addr >> PageShift); }
{ return PteAddr(addr >> PageShift); }
Addr level2() const
{ return AlphaISA::PteAddr(addr >> NPtePageShift + PageShift); }
{ return PteAddr(addr >> (NPtePageShift + PageShift)); }
Addr level1() const
{ return AlphaISA::PteAddr(addr >> 2 * NPtePageShift + PageShift); }
{ return PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
};
struct PageTableEntry
@ -92,6 +93,17 @@ namespace AlphaISA {
// ITB/DTB table entry
struct TlbEntry
{
Addr tag; // virtual page number tag
Addr ppn; // physical page number
uint8_t xre; // read permissions - VMEM_PERM_* mask
uint8_t xwe; // write permissions - VMEM_PERM_* mask
uint8_t asn; // address space number
bool asma; // address space match
bool fonr; // fault on read
bool fonw; // fault on write
bool valid; // valid page table entry
//Construct an entry that maps to physical address addr.
TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr)
{
@ -107,20 +119,19 @@ namespace AlphaISA {
fonw = false;
valid = true;
}
TlbEntry()
{}
Addr tag; // virtual page number tag
Addr ppn; // physical page number
uint8_t xre; // read permissions - VMEM_PERM_* mask
uint8_t xwe; // write permissions - VMEM_PERM_* mask
uint8_t asn; // address space number
bool asma; // address space match
bool fonr; // fault on read
bool fonw; // fault on write
bool valid; // valid page table entry
void
updateVaddr(Addr new_vaddr)
{
VAddr vaddr(new_vaddr);
tag = vaddr.vpn();
}
Addr pageStart()
Addr
pageStart()
{
return ppn << PageShift;
}
@ -129,6 +140,7 @@ namespace AlphaISA {
void unserialize(Checkpoint *cp, const std::string &section);
};
};
} // namespace AlphaISA
#endif // __ARCH_ALPHA_PAGETABLE_H__

View file

@ -38,39 +38,45 @@
class ThreadContext;
namespace AlphaISA
{
namespace AlphaISA {
class Predecoder
{
protected:
ThreadContext *tc;
// The extended machine instruction being generated
ExtMachInst ext_inst;
public:
Predecoder(ThreadContext * _tc) : tc(_tc)
Predecoder(ThreadContext * _tc)
: tc(_tc)
{}
ThreadContext * getTC()
ThreadContext *
getTC()
{
return tc;
}
void setTC(ThreadContext * _tc)
void
setTC(ThreadContext * _tc)
{
tc = _tc;
}
void process()
{
}
void
process()
{ }
void reset()
void
reset()
{ }
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
void
moreBytes(Addr pc, Addr fetchPC, MachInst inst)
{
ext_inst = inst;
#if FULL_SYSTEM
@ -78,22 +84,26 @@ namespace AlphaISA
#endif
}
bool needMoreBytes()
bool
needMoreBytes()
{
return true;
}
bool extMachInstReady()
bool
extMachInstReady()
{
return true;
}
// This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst & getExtMachInst()
const ExtMachInst &
getExtMachInst()
{
return ext_inst;
}
};
};
} // namespace AlphaISA
#endif // __ARCH_ALPHA_PREDECODER_HH__

View file

@ -32,14 +32,18 @@
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/process.hh"
#include "base/loader/object_file.hh"
#include "base/loader/elf_object.hh"
#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/process_impl.hh"
#include "sim/system.hh"
using namespace AlphaISA;
using namespace std;
static const int SyscallSuccessReg = 19;
AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params,
ObjectFile *objFile)
: LiveProcess(params, objFile)
@ -58,6 +62,117 @@ AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams * params,
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
}
void
AlphaLiveProcess::argsInit(int intSize, int pageSize)
{
objFile->loadSections(initVirtMem);
typedef AuxVector<uint64_t> auxv_t;
std::vector<auxv_t> auxv;
ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
if(elfObject)
{
// modern glibc uses a bunch of auxiliary vectors to set up
// TLS as well as do a bunch of other stuff
// these vectors go on the bottom of the stack, below argc/argv/envp
// pointers but above actual arg strings
// I don't have all the ones glibc looks at here, but so far it doesn't
// seem to be a problem.
// check out _dl_aux_init() in glibc/elf/dl-support.c for details
// --Lisa
auxv.push_back(auxv_t(M5_AT_PAGESZ, AlphaISA::VMPageSize));
auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable());
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
auxv.push_back(auxv_t(M5_AT_UID, uid()));
auxv.push_back(auxv_t(M5_AT_EUID, euid()));
auxv.push_back(auxv_t(M5_AT_GID, gid()));
auxv.push_back(auxv_t(M5_AT_EGID, egid()));
}
// Calculate how much space we need for arg & env & auxv arrays.
int argv_array_size = intSize * (argv.size() + 1);
int envp_array_size = intSize * (envp.size() + 1);
int auxv_array_size = intSize * 2 * (auxv.size() + 1);
int arg_data_size = 0;
for (int i = 0; i < argv.size(); ++i) {
arg_data_size += argv[i].size() + 1;
}
int env_data_size = 0;
for (int i = 0; i < envp.size(); ++i) {
env_data_size += envp[i].size() + 1;
}
int space_needed =
argv_array_size +
envp_array_size +
auxv_array_size +
arg_data_size +
env_data_size;
if (space_needed < 32*1024)
space_needed = 32*1024;
// set bottom of stack
stack_min = stack_base - space_needed;
// align it
stack_min = roundDown(stack_min, pageSize);
stack_size = stack_base - stack_min;
// map memory
pTable->allocate(stack_min, roundUp(stack_size, pageSize));
// map out initial stack contents
Addr argv_array_base = stack_min + intSize; // room for argc
Addr envp_array_base = argv_array_base + argv_array_size;
Addr auxv_array_base = envp_array_base + envp_array_size;
Addr arg_data_base = auxv_array_base + auxv_array_size;
Addr env_data_base = arg_data_base + arg_data_size;
// write contents to stack
uint64_t argc = argv.size();
if (intSize == 8)
argc = htog((uint64_t)argc);
else if (intSize == 4)
argc = htog((uint32_t)argc);
else
panic("Unknown int size");
initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize);
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
//Copy the aux stuff
for(int x = 0; x < auxv.size(); x++)
{
initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
(uint8_t*)&(auxv[x].a_type), intSize);
initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
(uint8_t*)&(auxv[x].a_val), intSize);
}
ThreadContext *tc = system->getThreadContext(contextIds[0]);
setSyscallArg(tc, 0, argc);
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
Addr prog_entry = objFile->entryPoint();
tc->setPC(prog_entry);
tc->setNextPC(prog_entry + sizeof(MachInst));
#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc
tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
#endif
}
void
@ -66,15 +181,49 @@ AlphaLiveProcess::startup()
if (checkpointRestored)
return;
Process::startup();
argsInit(MachineBytes, VMPageSize);
threadContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer());
//Opperate in user mode
threadContexts[0]->setMiscRegNoEffect(IPR_ICM, 0x18);
ThreadContext *tc = system->getThreadContext(contextIds[0]);
tc->setIntReg(GlobalPointerReg, objFile->globalPointer());
//Operate in user mode
tc->setMiscRegNoEffect(IPR_ICM, 0x18);
//No super page mapping
threadContexts[0]->setMiscRegNoEffect(IPR_MCSR, 0);
tc->setMiscRegNoEffect(IPR_MCSR, 0);
//Set this to 0 for now, but it should be unique for each process
threadContexts[0]->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
}
AlphaISA::IntReg
AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int i)
{
assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i);
}
void
AlphaLiveProcess::setSyscallArg(ThreadContext *tc,
int i, AlphaISA::IntReg val)
{
assert(i < 6);
tc->setIntReg(FirstArgumentReg + i, val);
}
void
AlphaLiveProcess::setSyscallReturn(ThreadContext *tc,
SyscallReturn return_value)
{
// check for error condition. Alpha syscall convention is to
// indicate success/failure in reg a3 (r19) and put the
// return value itself in the standard return value reg (v0).
if (return_value.successful()) {
// no error
tc->setIntReg(SyscallSuccessReg, 0);
tc->setIntReg(ReturnValueReg, return_value.value());
} else {
// got an error, return details
tc->setIntReg(SyscallSuccessReg, (IntReg)-1);
tc->setIntReg(ReturnValueReg, -return_value.value());
}
}

View file

@ -29,24 +29,24 @@
* Ali Saidi
*/
#ifndef __ALPHA_PROCESS_HH__
#define __ALPHA_PROCESS_HH__
#ifndef __ARCH_ALPHA_PROCESS_HH__
#define __ARCH_ALPHA_PROCESS_HH__
#include <string>
#include <vector>
#include "sim/process.hh"
class ObjectFile;
class System;
class AlphaLiveProcess : public LiveProcess
{
protected:
AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile);
void startup();
void argsInit(int intSize, int pageSize);
public:
AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int i);
void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};
#endif // __ALPHA_PROCESS_HH__
#endif // __ARCH_ALPHA_PROCESS_HH__

View file

@ -33,10 +33,12 @@
#include "arch/alpha/regfile.hh"
#include "cpu/thread_context.hh"
namespace AlphaISA
{
using namespace std;
namespace AlphaISA {
void
RegFile::serialize(std::ostream &os)
RegFile::serialize(EventManager *em, ostream &os)
{
intRegFile.serialize(os);
floatRegFile.serialize(os);
@ -49,7 +51,7 @@ namespace AlphaISA
}
void
RegFile::unserialize(Checkpoint *cp, const std::string &section)
RegFile::unserialize(EventManager *em, Checkpoint *cp, const string &section)
{
intRegFile.unserialize(cp, section);
floatRegFile.unserialize(cp, section);
@ -65,14 +67,12 @@ namespace AlphaISA
copyRegs(ThreadContext *src, ThreadContext *dest)
{
// First loop through the integer registers.
for (int i = 0; i < NumIntRegs; ++i) {
for (int i = 0; i < NumIntRegs; ++i)
dest->setIntReg(i, src->readIntReg(i));
}
// Then loop through the floating point registers.
for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
for (int i = 0; i < NumFloatRegs; ++i)
dest->setFloatRegBits(i, src->readFloatRegBits(i));
}
// Copy misc. registers
copyMiscRegs(src, dest);
@ -85,15 +85,16 @@ namespace AlphaISA
void
copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
dest->setMiscRegNoEffect(AlphaISA::MISCREG_FPCR,
src->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR));
dest->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ,
src->readMiscRegNoEffect(AlphaISA::MISCREG_UNIQ));
dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG,
src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG));
dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR,
src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR));
dest->setMiscRegNoEffect(MISCREG_FPCR,
src->readMiscRegNoEffect(MISCREG_FPCR));
dest->setMiscRegNoEffect(MISCREG_UNIQ,
src->readMiscRegNoEffect(MISCREG_UNIQ));
dest->setMiscRegNoEffect(MISCREG_LOCKFLAG,
src->readMiscRegNoEffect(MISCREG_LOCKFLAG));
dest->setMiscRegNoEffect(MISCREG_LOCKADDR,
src->readMiscRegNoEffect(MISCREG_LOCKADDR));
copyIprs(src, dest);
}
}
} // namespace AlphaISA

View file

@ -43,45 +43,50 @@
//XXX These should be implemented by someone who knows the alpha stuff better
class Checkpoint;
class EventManager;
class ThreadContext;
namespace AlphaISA
{
namespace AlphaISA {
class RegFile {
protected:
Addr pc; // program counter
Addr npc; // next-cycle program counter
Addr nnpc;
Addr nnpc; // next next-cycle program counter
public:
Addr readPC()
Addr
readPC()
{
return pc;
}
void setPC(Addr val)
void
setPC(Addr val)
{
pc = val;
}
Addr readNextPC()
Addr
readNextPC()
{
return npc;
}
void setNextPC(Addr val)
void
setNextPC(Addr val)
{
npc = val;
}
Addr readNextNPC()
Addr
readNextNPC()
{
return npc + sizeof(MachInst);
}
void setNextNPC(Addr val)
void
setNextNPC(Addr val)
{ }
protected:
@ -90,109 +95,127 @@ namespace AlphaISA
MiscRegFile miscRegFile; // control register file
public:
#if FULL_SYSTEM
int intrflag; // interrupt flag
inline int instAsid()
{ return miscRegFile.getInstAsid(); }
inline int dataAsid()
{ return miscRegFile.getDataAsid(); }
int
instAsid()
{
return miscRegFile.getInstAsid();
}
int
dataAsid()
{
return miscRegFile.getDataAsid();
}
#endif // FULL_SYSTEM
void clear()
void
clear()
{
intRegFile.clear();
floatRegFile.clear();
miscRegFile.clear();
}
MiscReg readMiscRegNoEffect(int miscReg)
MiscReg
readMiscRegNoEffect(int miscReg)
{
return miscRegFile.readRegNoEffect(miscReg);
}
MiscReg readMiscReg(int miscReg, ThreadContext *tc)
MiscReg
readMiscReg(int miscReg, ThreadContext *tc)
{
return miscRegFile.readReg(miscReg, tc);
}
void setMiscRegNoEffect(int miscReg, const MiscReg &val)
void
setMiscRegNoEffect(int miscReg, const MiscReg &val)
{
miscRegFile.setRegNoEffect(miscReg, val);
}
void setMiscReg(int miscReg, const MiscReg &val,
ThreadContext * tc)
void
setMiscReg(int miscReg, const MiscReg &val, ThreadContext *tc)
{
miscRegFile.setReg(miscReg, val, tc);
}
FloatReg readFloatReg(int floatReg)
FloatReg
readFloatReg(int floatReg)
{
return floatRegFile.d[floatReg];
}
FloatReg readFloatReg(int floatReg, int width)
FloatReg
readFloatReg(int floatReg, int width)
{
return readFloatReg(floatReg);
}
FloatRegBits readFloatRegBits(int floatReg)
FloatRegBits
readFloatRegBits(int floatReg)
{
return floatRegFile.q[floatReg];
}
FloatRegBits readFloatRegBits(int floatReg, int width)
FloatRegBits
readFloatRegBits(int floatReg, int width)
{
return readFloatRegBits(floatReg);
}
void setFloatReg(int floatReg, const FloatReg &val)
void
setFloatReg(int floatReg, const FloatReg &val)
{
floatRegFile.d[floatReg] = val;
}
void setFloatReg(int floatReg, const FloatReg &val, int width)
void
setFloatReg(int floatReg, const FloatReg &val, int width)
{
setFloatReg(floatReg, val);
}
void setFloatRegBits(int floatReg, const FloatRegBits &val)
void
setFloatRegBits(int floatReg, const FloatRegBits &val)
{
floatRegFile.q[floatReg] = val;
}
void setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
void
setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
{
setFloatRegBits(floatReg, val);
}
IntReg readIntReg(int intReg)
IntReg
readIntReg(int intReg)
{
return intRegFile.readReg(intReg);
}
void setIntReg(int intReg, const IntReg &val)
void
setIntReg(int intReg, const IntReg &val)
{
intRegFile.setReg(intReg, val);
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
void changeContext(RegContextParam param, RegContextVal val)
{
//This would be an alternative place to call/implement
//the swapPALShadow function
}
void serialize(EventManager *em, std::ostream &os);
void unserialize(EventManager *em, Checkpoint *cp,
const std::string &section);
};
static inline int flattenIntIndex(ThreadContext * tc, int reg)
static inline int
flattenIntIndex(ThreadContext * tc, int reg)
{
return reg;
}
static inline int flattenFloatIndex(ThreadContext * tc, int reg)
static inline int
flattenFloatIndex(ThreadContext * tc, int reg)
{
return reg;
}
@ -200,6 +223,7 @@ namespace AlphaISA
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
} // namespace AlphaISA
#endif
#endif // __ARCH_ALPHA_REGFILE_HH__

View file

@ -117,9 +117,9 @@
*/
#include <sys/signal.h>
#include <unistd.h>
#include <string>
#include <unistd.h>
#include "config/full_system.hh"
#if FULL_SYSTEM
@ -140,19 +140,17 @@
#include "sim/system.hh"
using namespace std;
using namespace TheISA;
using namespace AlphaISA;
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
: BaseRemoteGDB(_system, c, KGDB_NUMREGS)
RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc)
: BaseRemoteGDB(_system, tc, KGDB_NUMREGS)
{
memset(gdbregs.regs, 0, gdbregs.bytes());
}
///////////////////////////////////////////////////////////
// RemoteGDB::acc
//
// Determine if the mapping at va..(va+len) is valid.
//
/*
* Determine if the mapping at va..(va+len) is valid.
*/
bool
RemoteGDB::acc(Addr va, size_t len)
{
@ -161,12 +159,12 @@ RemoteGDB::acc(Addr va, size_t len)
#else
Addr last_va;
va = TheISA::TruncPage(va);
last_va = TheISA::RoundPage(va + len);
va = TruncPage(va);
last_va = RoundPage(va + len);
do {
if (TheISA::IsK0Seg(va)) {
if (va < (TheISA::K0SegBase + pmem->size())) {
if (IsK0Seg(va)) {
if (va < (K0SegBase + pmem->size())) {
DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
"%#x < K0SEG + size\n", va);
return true;
@ -178,22 +176,24 @@ RemoteGDB::acc(Addr va, size_t len)
}
/**
* This code says that all accesses to palcode (instruction and data)
* are valid since there isn't a va->pa mapping because palcode is
* accessed physically. At some point this should probably be cleaned up
* but there is no easy way to do it.
* This code says that all accesses to palcode (instruction
* and data) are valid since there isn't a va->pa mapping
* because palcode is accessed physically. At some point this
* should probably be cleaned up but there is no easy way to
* do it.
*/
if (AlphaISA::PcPAL(va) || va < 0x10000)
if (PcPAL(va) || va < 0x10000)
return true;
Addr ptbr = context->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20);
TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va);
Addr ptbr = context->readMiscRegNoEffect(IPR_PALtemp20);
PageTableEntry pte =
kernel_pte_lookup(context->getPhysPort(), ptbr, va);
if (!pte.valid()) {
DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
return false;
}
va += TheISA::PageBytes;
va += PageBytes;
} while (va < last_va);
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
@ -201,11 +201,10 @@ RemoteGDB::acc(Addr va, size_t len)
#endif
}
///////////////////////////////////////////////////////////
// RemoteGDB::getregs
//
// Translate the kernel debugger register format into
// the GDB register format.
/*
* Translate the kernel debugger register format into the GDB register
* format.
*/
void
RemoteGDB::getregs()
{
@ -214,45 +213,43 @@ RemoteGDB::getregs()
gdbregs.regs[KGDB_REG_PC] = context->readPC();
// @todo: Currently this is very Alpha specific.
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
if (PcPAL(gdbregs.regs[KGDB_REG_PC])) {
for (int i = 0; i < NumIntArchRegs; ++i) {
gdbregs.regs[i] = context->readIntReg(reg_redir[i]);
}
} else {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
for (int i = 0; i < NumIntArchRegs; ++i) {
gdbregs.regs[i] = context->readIntReg(i);
}
}
#ifdef KGDB_FP_REGS
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
for (int i = 0; i < NumFloatArchRegs; ++i) {
gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
}
#endif
}
///////////////////////////////////////////////////////////
// RemoteGDB::setregs
//
// Translate the GDB register format into the kernel
// debugger register format.
//
/*
* Translate the GDB register format into the kernel debugger register
* format.
*/
void
RemoteGDB::setregs()
{
// @todo: Currently this is very Alpha specific.
if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]);
if (PcPAL(gdbregs.regs[KGDB_REG_PC])) {
for (int i = 0; i < NumIntArchRegs; ++i) {
context->setIntReg(reg_redir[i], gdbregs.regs[i]);
}
} else {
for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
for (int i = 0; i < NumIntArchRegs; ++i) {
context->setIntReg(i, gdbregs.regs[i]);
}
}
#ifdef KGDB_FP_REGS
for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
for (int i = 0; i < NumFloatArchRegs; ++i) {
context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
}
#endif

View file

@ -44,18 +44,13 @@ class System;
class ThreadContext;
class PhysicalMemory;
namespace AlphaISA
{
namespace AlphaISA {
class RemoteGDB : public BaseRemoteGDB
{
protected:
// Machine memory
bool write(Addr addr, size_t size, const char *data);
public:
RemoteGDB(System *system, ThreadContext *context);
bool acc(Addr addr, size_t len);
Addr notTakenBkpt;
Addr takenBkpt;
protected:
void getregs();
@ -64,11 +59,14 @@ namespace AlphaISA
void clearSingleStep();
void setSingleStep();
protected:
// Machine memory
bool acc(Addr addr, size_t len);
bool write(Addr addr, size_t size, const char *data);
Addr notTakenBkpt;
Addr takenBkpt;
public:
RemoteGDB(System *system, ThreadContext *context);
};
}
#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */
} // namespace AlphaISA
#endif // __ARCH_ALPHA_REMOTE_GDB_HH__

View file

@ -41,38 +41,34 @@
using namespace std;
namespace AlphaISA
{
namespace AlphaISA {
ProcessInfo::ProcessInfo(ThreadContext *_tc)
: tc(_tc)
{
Addr addr = 0;
VirtualPort *vp = tc->getVirtPort();
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
VirtualPort *vp;
vp = tc->getVirtPort();
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
if (!symtab->findAddress("thread_info_size", addr))
panic("thread info not compiled into kernel\n");
thread_info_size = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
if (!symtab->findAddress("task_struct_size", addr))
panic("thread info not compiled into kernel\n");
task_struct_size = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
if (!symtab->findAddress("thread_info_task", addr))
panic("thread info not compiled into kernel\n");
task_off = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
if (!symtab->findAddress("task_struct_pid", addr))
panic("thread info not compiled into kernel\n");
pid_off = vp->readGtoH<int32_t>(addr);
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
if (!symtab->findAddress("task_struct_comm", addr))
panic("thread info not compiled into kernel\n");
name_off = vp->readGtoH<int32_t>(addr);
tc->delVirtPort(vp);
}
Addr
@ -88,7 +84,6 @@ namespace AlphaISA
vp = tc->getVirtPort();
tsk = vp->readGtoH<Addr>(base + task_off);
tc->delVirtPort(vp);
return tsk;
}
@ -106,7 +101,6 @@ namespace AlphaISA
vp = tc->getVirtPort();
pd = vp->readGtoH<uint16_t>(task + pid_off);
tc->delVirtPort(vp);
return pd;
}
@ -146,11 +140,13 @@ namespace AlphaISA
{
tc = _tc;
bool usermode = (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
System *sys = tc->getSystemPtr();
bool usermode =
(tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
Addr pc = tc->readNextPC();
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
pc <= tc->getSystemPtr()->kernelEnd;
bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
if (usermode) {
stack.push_back(user);
@ -162,12 +158,12 @@ namespace AlphaISA
return;
}
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
Addr ksp = tc->readIntReg(TheISA::StackPointerReg);
SymbolTable *symtab = sys->kernelSymtab;
Addr ksp = tc->readIntReg(StackPointerReg);
Addr bottom = ksp & ~0x3fff;
Addr addr;
if (is_call) {
Addr addr;
if (!symtab->findNearestAddr(pc, addr))
panic("could not find address %#x", pc);
@ -175,10 +171,8 @@ namespace AlphaISA
pc = tc->readPC();
}
Addr ra;
int size;
while (ksp > bottom) {
Addr addr;
if (!symtab->findNearestAddr(pc, addr))
panic("could not find symbol for pc=%#x", pc);
assert(pc >= addr && "symbol botch: callpc < func");
@ -188,6 +182,8 @@ namespace AlphaISA
if (isEntry(addr))
return;
Addr ra;
int size;
if (decodePrologue(ksp, pc, addr, size, ra)) {
if (!ra)
return;
@ -204,8 +200,7 @@ namespace AlphaISA
return;
}
bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
pc <= tc->getSystemPtr()->kernelEnd;
bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
if (!kernel)
return;
@ -219,22 +214,22 @@ namespace AlphaISA
bool
StackTrace::isEntry(Addr addr)
{
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp12))
if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12))
return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp7))
if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7))
return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp11))
if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11))
return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp21))
if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21))
return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp9))
if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9))
return true;
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp2))
if (addr == tc->readMiscRegNoEffect(IPR_PALtemp2))
return true;
return false;
@ -311,8 +306,8 @@ namespace AlphaISA
* which registers are stored where, and how large the stack frame is.
*/
bool
StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
int &size, Addr &ra)
StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, int &size,
Addr &ra)
{
size = 0;
ra = 0;
@ -367,4 +362,5 @@ namespace AlphaISA
}
}
#endif
}
} // namespace AlphaISA

View file

@ -36,8 +36,8 @@
class ThreadContext;
namespace AlphaISA
{
namespace AlphaISA {
class StackTrace;
class ProcessInfo
@ -61,8 +61,6 @@ namespace AlphaISA
class StackTrace
{
protected:
typedef TheISA::MachInst MachInst;
private:
ThreadContext *tc;
std::vector<Addr> stack;
@ -80,7 +78,8 @@ namespace AlphaISA
StackTrace(ThreadContext *tc, StaticInstPtr inst);
~StackTrace();
void clear()
void
clear()
{
tc = 0;
stack.clear();
@ -120,6 +119,7 @@ namespace AlphaISA
trace(tc, !inst->isReturn());
return true;
}
}
} // namespace AlphaISA
#endif // __ARCH_ALPHA_STACKTRACE_HH__

View file

@ -42,8 +42,7 @@
#include "params/AlphaSystem.hh"
#include "sim/byteswap.hh"
using namespace LittleEndianGuest;
using namespace AlphaISA;
AlphaSystem::AlphaSystem(Params *p)
: System(p)
@ -67,8 +66,8 @@ AlphaSystem::AlphaSystem(Params *p)
// Load program sections into memory
pal->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
console->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
pal->loadSections(&functionalPort, LoadAddrMask);
console->loadSections(&functionalPort, LoadAddrMask);
// load symbols
if (!console->loadGlobalSymbols(consoleSymtab))
@ -117,7 +116,6 @@ AlphaSystem::AlphaSystem(Params *p)
virtPort.write(addr+0x58, data);
} else
panic("could not find hwrpb\n");
}
AlphaSystem::~AlphaSystem()
@ -172,11 +170,11 @@ AlphaSystem::fixFuncEventAddr(Addr addr)
const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
uint32_t i1 = virtPort.read<uint32_t>(addr);
uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(AlphaISA::MachInst));
uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(MachInst));
if ((i1 & inst_mask) == gp_ldah_pattern &&
(i2 & inst_mask) == gp_lda_pattern) {
Addr new_addr = addr + 2* sizeof(AlphaISA::MachInst);
Addr new_addr = addr + 2 * sizeof(MachInst);
DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
return new_addr;
} else {
@ -184,16 +182,16 @@ AlphaSystem::fixFuncEventAddr(Addr addr)
}
}
void
AlphaSystem::setAlphaAccess(Addr access)
{
Addr addr = 0;
if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
virtPort.write(addr, htog(EV5::Phys2K0Seg(access)));
} else
virtPort.write(addr, htog(Phys2K0Seg(access)));
} else {
panic("could not find m5AlphaAccess\n");
}
}
void
AlphaSystem::serialize(std::ostream &os)
@ -203,7 +201,6 @@ AlphaSystem::serialize(std::ostream &os)
palSymtab->serialize("pal_symtab", os);
}
void
AlphaSystem::unserialize(Checkpoint *cp, const std::string &section)
{

View file

@ -49,10 +49,10 @@ class AlphaSystem : public System
AlphaSystem(Params *p);
~AlphaSystem();
public:
/**
* Serialization stuff
*/
public:
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
@ -77,26 +77,28 @@ class AlphaSystem : public System
/** Event to halt the simulator if the console calls panic() */
BreakPCEvent *consolePanicEvent;
#endif
protected:
const Params *params() const { return (const Params *)_params; }
/** Add a function-based event to PALcode. */
template <class T>
T *addPalFuncEvent(const char *lbl)
T *
addPalFuncEvent(const char *lbl)
{
return addFuncEvent<T>(palSymtab, lbl);
}
/** Add a function-based event to the console code. */
template <class T>
T *addConsoleFuncEvent(const char *lbl)
T *
addConsoleFuncEvent(const char *lbl)
{
return addFuncEvent<T>(consoleSymtab, lbl);
}
virtual Addr fixFuncEventAddr(Addr addr);
};
#endif
#endif // __ARCH_ALPHA_SYSTEM_HH__

View file

@ -43,13 +43,14 @@
#include "cpu/thread_context.hh"
using namespace std;
using namespace EV5;
namespace AlphaISA {
///////////////////////////////////////////////////////////////////////
//
// Alpha TLB
//
#ifdef DEBUG
bool uncacheBit39 = false;
bool uncacheBit40 = false;
@ -114,19 +115,19 @@ TLB::lookup(Addr vpn, uint8_t asn)
return retval;
}
Fault
TLB::checkCacheability(RequestPtr &req)
TLB::checkCacheability(RequestPtr &req, bool itb)
{
// in Alpha, cacheability is controlled by upper-level bits of the
// physical address
/*
* We support having the uncacheable bit in either bit 39 or bit 40.
* The Turbolaser platform (and EV5) support having the bit in 39, but
* Tsunami (which Linux assumes uses an EV6) generates accesses with
* the bit in 40. So we must check for both, but we have debug flags
* to catch a weird case where both are used, which shouldn't happen.
* We support having the uncacheable bit in either bit 39 or bit
* 40. The Turbolaser platform (and EV5) support having the bit
* in 39, but Tsunami (which Linux assumes uses an EV6) generates
* accesses with the bit in 40. So we must check for both, but we
* have debug flags to catch a weird case where both are used,
* which shouldn't happen.
*/
@ -141,13 +142,20 @@ TLB::checkCacheability(RequestPtr &req)
return new UnimpFault("IPR memory space not implemented!");
} else {
// mark request as uncacheable
req->setFlags(req->getFlags() | UNCACHEABLE);
req->setFlags(Request::UNCACHEABLE);
#if !ALPHA_TLASER
// Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
// Clear bits 42:35 of the physical address (10-2 in
// Tsunami manual)
req->setPaddr(req->getPaddr() & PAddrUncachedMask);
#endif
}
// We shouldn't be able to read from an uncachable address in Alpha as
// we don't have a ROM and we don't want to try to fetch from a device
// register as we destroy any data that is clear-on-read.
if (req->isUncacheable() && itb)
return new UnimpFault("CPU trying to fetch from uncached I/O");
}
return NoFault;
}
@ -216,7 +224,8 @@ TLB::flushProcesses()
++i;
if (!entry->asma) {
DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, entry->tag, entry->ppn);
DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index,
entry->tag, entry->ppn);
entry->valid = false;
lookupTable.erase(cur);
}
@ -279,7 +288,6 @@ TLB::unserialize(Checkpoint *cp, const string &section)
}
}
///////////////////////////////////////////////////////////////////////
//
// Alpha ITB
@ -308,13 +316,12 @@ ITB::regStats()
accesses = hits + misses;
}
Fault
ITB::translate(RequestPtr &req, ThreadContext *tc)
ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
{
//If this is a pal pc, then set PHYSICAL
if (FULL_SYSTEM && PcPAL(req->getPC()))
req->setFlags(req->getFlags() | PHYSICAL);
req->setFlags(Request::PHYSICAL);
if (PcPAL(req->getPC())) {
// strip off PAL PC marker (lsb is 1)
@ -323,7 +330,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
return NoFault;
}
if (req->getFlags() & PHYSICAL) {
if (req->getFlags() & Request::PHYSICAL) {
req->setPaddr(req->getVaddr());
} else {
// verify that this is a good virtual address
@ -390,10 +397,18 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
if (req->getPaddr() & ~PAddrImplMask)
return genMachineCheckFault();
return checkCacheability(req);
return checkCacheability(req, true);
}
void
ITB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation)
{
assert(translation);
translation->finish(translateAtomic(req, tc), req, tc, false);
}
///////////////////////////////////////////////////////////////////////
//
// Alpha DTB
@ -472,14 +487,13 @@ DTB::regStats()
}
Fault
DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
{
Addr pc = tc->readPC();
mode_type mode =
(mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM));
/**
* Check for alignment faults
*/
@ -491,13 +505,13 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
}
if (PcPAL(pc)) {
mode = (req->getFlags() & ALTMODE) ?
mode = (req->getFlags() & Request::ALTMODE) ?
(mode_type)ALT_MODE_AM(
tc->readMiscRegNoEffect(IPR_ALT_MODE))
: mode_kernel;
}
if (req->getFlags() & PHYSICAL) {
if (req->getFlags() & Request::PHYSICAL) {
req->setPaddr(req->getVaddr());
} else {
// verify that this is a good virtual address
@ -517,14 +531,15 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
if (VAddrSpaceEV6(req->getVaddr()) == 0x7e)
#endif
{
// only valid in kernel mode
if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) !=
mode_kernel) {
if (write) { write_acv++; } else { read_acv++; }
uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
MM_STAT_ACV_MASK);
return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
return new DtbAcvFault(req->getVaddr(), req->getFlags(),
flags);
}
req->setPaddr(req->getVaddr() & PAddrImplMask);
@ -553,7 +568,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
if (write) { write_misses++; } else { read_misses++; }
uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
MM_STAT_DTB_MISS_MASK;
return (req->getFlags() & VPTE) ?
return (req->getFlags() & Request::VPTE) ?
(Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
flags)) :
(Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
@ -570,25 +585,28 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
uint64_t flags = MM_STAT_WR_MASK |
MM_STAT_ACV_MASK |
(entry->fonw ? MM_STAT_FONW_MASK : 0);
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
return new DtbPageFault(req->getVaddr(), req->getFlags(),
flags);
}
if (entry->fonw) {
write_acv++;
uint64_t flags = MM_STAT_WR_MASK |
MM_STAT_FONW_MASK;
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
uint64_t flags = MM_STAT_WR_MASK | MM_STAT_FONW_MASK;
return new DtbPageFault(req->getVaddr(), req->getFlags(),
flags);
}
} else {
if (!(entry->xre & MODE2MASK(mode))) {
read_acv++;
uint64_t flags = MM_STAT_ACV_MASK |
(entry->fonr ? MM_STAT_FONR_MASK : 0);
return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
return new DtbAcvFault(req->getVaddr(), req->getFlags(),
flags);
}
if (entry->fonr) {
read_acv++;
uint64_t flags = MM_STAT_FONR_MASK;
return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
return new DtbPageFault(req->getVaddr(), req->getFlags(),
flags);
}
}
}
@ -606,6 +624,14 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
return checkCacheability(req);
}
void
DTB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, bool write)
{
assert(translation);
translation->finish(translateAtomic(req, tc, write), req, tc, write);
}
TlbEntry &
TLB::index(bool advance)
{

View file

@ -29,8 +29,8 @@
* Steve Reinhardt
*/
#ifndef __ALPHA_MEMORY_HH__
#define __ALPHA_MEMORY_HH__
#ifndef __ARCH_ALPHA_TLB_HH__
#define __ARCH_ALPHA_TLB_HH__
#include <map>
@ -48,8 +48,8 @@
class ThreadContext;
namespace AlphaISA
{
namespace AlphaISA {
class TlbEntry;
class TLB : public BaseTLB
@ -79,20 +79,23 @@ namespace AlphaISA
void flushProcesses();
void flushAddr(Addr addr, uint8_t asn);
void demapPage(Addr vaddr, uint64_t asn)
void
demapPage(Addr vaddr, uint64_t asn)
{
assert(asn < (1 << 8));
flushAddr(vaddr, asn);
}
// static helper functions... really EV5 VM traits
static bool validVirtualAddress(Addr vaddr) {
static bool
validVirtualAddress(Addr vaddr)
{
// unimplemented bits must be all 0 or all 1
Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
Addr unimplBits = vaddr & VAddrUnImplMask;
return unimplBits == 0 || unimplBits == VAddrUnImplMask;
}
static Fault checkCacheability(RequestPtr &req);
static Fault checkCacheability(RequestPtr &req, bool itb = false);
// Checkpointing
virtual void serialize(std::ostream &os);
@ -100,12 +103,14 @@ namespace AlphaISA
// Most recently used page table entries
TlbEntry *EntryCache[3];
inline void flushCache()
inline void
flushCache()
{
memset(EntryCache, 0, 3 * sizeof(TlbEntry*));
}
inline TlbEntry* updateCache(TlbEntry *entry) {
inline TlbEntry *
updateCache(TlbEntry *entry) {
EntryCache[2] = EntryCache[1];
EntryCache[1] = EntryCache[0];
EntryCache[0] = entry;
@ -116,9 +121,9 @@ namespace AlphaISA
class ITB : public TLB
{
protected:
mutable Stats::Scalar<> hits;
mutable Stats::Scalar<> misses;
mutable Stats::Scalar<> acv;
mutable Stats::Scalar hits;
mutable Stats::Scalar misses;
mutable Stats::Scalar acv;
mutable Stats::Formula accesses;
public:
@ -126,20 +131,22 @@ namespace AlphaISA
ITB(const Params *p);
virtual void regStats();
Fault translate(RequestPtr &req, ThreadContext *tc);
Fault translateAtomic(RequestPtr req, ThreadContext *tc);
void translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation);
};
class DTB : public TLB
{
protected:
mutable Stats::Scalar<> read_hits;
mutable Stats::Scalar<> read_misses;
mutable Stats::Scalar<> read_acv;
mutable Stats::Scalar<> read_accesses;
mutable Stats::Scalar<> write_hits;
mutable Stats::Scalar<> write_misses;
mutable Stats::Scalar<> write_acv;
mutable Stats::Scalar<> write_accesses;
mutable Stats::Scalar read_hits;
mutable Stats::Scalar read_misses;
mutable Stats::Scalar read_acv;
mutable Stats::Scalar read_accesses;
mutable Stats::Scalar write_hits;
mutable Stats::Scalar write_misses;
mutable Stats::Scalar write_acv;
mutable Stats::Scalar write_accesses;
Stats::Formula hits;
Stats::Formula misses;
Stats::Formula acv;
@ -150,8 +157,11 @@ namespace AlphaISA
DTB(const Params *p);
virtual void regStats();
Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write);
void translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, bool write);
};
}
#endif // __ALPHA_MEMORY_HH__
} // namespace AlphaISA
#endif // __ARCH_ALPHA_TLB_HH__

View file

@ -32,10 +32,8 @@
#include "arch/alpha/tru64/tru64.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/tru64/process.hh"
#include "cpu/thread_context.hh"
#include "kern/tru64/tru64.hh"
#include "sim/process.hh"
#include "sim/syscall_emul.hh"
@ -47,7 +45,7 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
TypedBufferArg<AlphaTru64::utsname> name(tc->getSyscallArg(0));
TypedBufferArg<AlphaTru64::utsname> name(process->getSyscallArg(tc, 0));
strcpy(name->sysname, "OSF1");
strcpy(name->nodename, "m5.eecs.umich.edu");
@ -64,34 +62,35 @@ static SyscallReturn
getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = tc->getSyscallArg(0);
unsigned nbytes = tc->getSyscallArg(2);
unsigned op = process->getSyscallArg(tc, 0);
unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) {
case AlphaTru64::GSI_MAX_CPU: {
TypedBufferArg<uint32_t> max_cpu(tc->getSyscallArg(1));
TypedBufferArg<uint32_t> max_cpu(process->getSyscallArg(tc, 1));
*max_cpu = htog((uint32_t)process->numCpus());
max_cpu.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_CPUS_IN_BOX: {
TypedBufferArg<uint32_t> cpus_in_box(tc->getSyscallArg(1));
TypedBufferArg<uint32_t> cpus_in_box(process->getSyscallArg(tc, 1));
*cpus_in_box = htog((uint32_t)process->numCpus());
cpus_in_box.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_PHYSMEM: {
TypedBufferArg<uint64_t> physmem(tc->getSyscallArg(1));
TypedBufferArg<uint64_t> physmem(process->getSyscallArg(tc, 1));
*physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
physmem.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_CPU_INFO: {
TypedBufferArg<AlphaTru64::cpu_info> infop(tc->getSyscallArg(1));
TypedBufferArg<AlphaTru64::cpu_info>
infop(process->getSyscallArg(tc, 1));
infop->current_cpu = htog(0);
infop->cpus_in_box = htog(process->numCpus());
@ -108,14 +107,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
case AlphaTru64::GSI_PROC_TYPE: {
TypedBufferArg<uint64_t> proc_type(tc->getSyscallArg(1));
TypedBufferArg<uint64_t> proc_type(process->getSyscallArg(tc, 1));
*proc_type = htog((uint64_t)11);
proc_type.copyOut(tc->getMemPort());
return 1;
}
case AlphaTru64::GSI_PLATFORM_NAME: {
BufferArg bufArg(tc->getSyscallArg(1), nbytes);
BufferArg bufArg(process->getSyscallArg(tc, 1), nbytes);
strncpy((char *)bufArg.bufferPtr(),
"COMPAQ Professional Workstation XP1000",
nbytes);
@ -124,7 +123,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
case AlphaTru64::GSI_CLK_TCK: {
TypedBufferArg<uint64_t> clk_hz(tc->getSyscallArg(1));
TypedBufferArg<uint64_t> clk_hz(process->getSyscallArg(tc, 1));
*clk_hz = htog((uint64_t)1024);
clk_hz.copyOut(tc->getMemPort());
return 1;
@ -143,12 +142,12 @@ static SyscallReturn
setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
unsigned op = tc->getSyscallArg(0);
unsigned op = process->getSyscallArg(tc, 0);
switch (op) {
case AlphaTru64::SSI_IEEE_FP_CONTROL:
warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
tc->getSyscallArg(1));
process->getSyscallArg(tc, 1));
break;
default:
@ -159,26 +158,24 @@ setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return 0;
}
/// Target table() handler.
static
SyscallReturn tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
static SyscallReturn
tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
using namespace std;
using namespace TheISA;
int id = tc->getSyscallArg(0); // table ID
int index = tc->getSyscallArg(1); // index into table
int id = process->getSyscallArg(tc, 0); // table ID
int index = process->getSyscallArg(tc, 1); // index into table
// arg 2 is buffer pointer; type depends on table ID
int nel = tc->getSyscallArg(3); // number of elements
int lel = tc->getSyscallArg(4); // expected element size
int nel = process->getSyscallArg(tc, 3); // number of elements
int lel = process->getSyscallArg(tc, 4); // expected element size
switch (id) {
case AlphaTru64::TBL_SYSINFO: {
if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
return -EINVAL;
TypedBufferArg<Tru64::tbl_sysinfo> elp(tc->getSyscallArg(2));
TypedBufferArg<Tru64::tbl_sysinfo> elp(process->getSyscallArg(tc, 2));
const int clk_hz = one_million;
elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));
@ -219,7 +216,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 14 */ SyscallDesc("mknod", unimplementedFunc),
/* 15 */ SyscallDesc("chmod", unimplementedFunc),
/* 16 */ SyscallDesc("chown", unimplementedFunc),
/* 17 */ SyscallDesc("obreak", obreakFunc),
/* 17 */ SyscallDesc("obreak", brkFunc),
/* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", lseekFunc),
/* 20 */ SyscallDesc("getpid", getpidPseudoFunc),
@ -260,9 +257,9 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 55 */ SyscallDesc("reboot", unimplementedFunc),
/* 56 */ SyscallDesc("revoke", unimplementedFunc),
/* 57 */ SyscallDesc("symlink", unimplementedFunc),
/* 58 */ SyscallDesc("readlink", unimplementedFunc),
/* 58 */ SyscallDesc("readlink", readlinkFunc),
/* 59 */ SyscallDesc("execve", unimplementedFunc),
/* 60 */ SyscallDesc("umask", unimplementedFunc),
/* 60 */ SyscallDesc("umask", umaskFunc),
/* 61 */ SyscallDesc("chroot", unimplementedFunc),
/* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
/* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
@ -339,7 +336,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 133 */ SyscallDesc("sendto", unimplementedFunc),
/* 134 */ SyscallDesc("shutdown", unimplementedFunc),
/* 135 */ SyscallDesc("socketpair", unimplementedFunc),
/* 136 */ SyscallDesc("mkdir", unimplementedFunc),
/* 136 */ SyscallDesc("mkdir", mkdirFunc),
/* 137 */ SyscallDesc("rmdir", unimplementedFunc),
/* 138 */ SyscallDesc("utimes", unimplementedFunc),
/* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
@ -472,15 +469,14 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 266 */ SyscallDesc("sendfile", unimplementedFunc),
};
SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 1 */ SyscallDesc("m5_mutex_lock", AlphaTru64::m5_mutex_lockFunc),
/* 2 */ SyscallDesc("m5_mutex_trylock", AlphaTru64::m5_mutex_trylockFunc),
/* 3 */ SyscallDesc("m5_mutex_unlock", AlphaTru64::m5_mutex_unlockFunc),
/* 4 */ SyscallDesc("m5_cond_signal", AlphaTru64::m5_cond_signalFunc),
/* 5 */ SyscallDesc("m5_cond_broadcast", AlphaTru64::m5_cond_broadcastFunc),
/* 5 */ SyscallDesc("m5_cond_broadcast",
AlphaTru64::m5_cond_broadcastFunc),
/* 6 */ SyscallDesc("m5_cond_wait", AlphaTru64::m5_cond_waitFunc),
/* 7 */ SyscallDesc("m5_thread_exit", AlphaTru64::m5_thread_exitFunc),
/* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
@ -507,7 +503,8 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
/* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
/* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
/* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
/* 32 */ SyscallDesc("nxm_thread_create", AlphaTru64::nxm_thread_createFunc),
/* 32 */ SyscallDesc("nxm_thread_create",
AlphaTru64::nxm_thread_createFunc),
/* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc),
/* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
/* 35 */ SyscallDesc("nxm_idle", AlphaTru64::nxm_idleFunc),
@ -572,7 +569,6 @@ AlphaTru64Process::getDesc(int callnum)
return &syscallDescs[callnum];
}
AlphaTru64Process::AlphaTru64Process(LiveProcessParams *params,
ObjectFile *objFile)
: AlphaLiveProcess(params, objFile),

View file

@ -28,12 +28,13 @@
* Authors: Steve Reinhardt
*/
#ifndef __ALPHA_TRU64_PROCESS_HH__
#define __ALPHA_TRU64_PROCESS_HH__
#ifndef __ARCH_ALPHA_TRU64_PROCESS_HH__
#define __ARCH_ALPHA_TRU64_PROCESS_HH__
#include "arch/alpha/process.hh"
namespace AlphaISA {
/// A process with emulated Alpha Tru64 syscalls.
class AlphaTru64Process : public AlphaLiveProcess
{
@ -56,4 +57,4 @@ class AlphaTru64Process : public AlphaLiveProcess
} // namespace AlphaISA
#endif // __ALPHA_TRU64_PROCESS_HH__
#endif // __ARCH_ALPHA_TRU64_PROCESS_HH__

View file

@ -28,14 +28,13 @@
* Authors: Korey Sewell
*/
#ifndef __ALPHA_ALPHA_TRU64_HH
#define __ALPHA_ALPHA_TRU64_HH
#ifndef __ALPHA_ALPHA_TRU64_TRU64_HH__
#define __ALPHA_ALPHA_TRU64_TRU64_HH__
#include "kern/tru64/tru64.hh"
class AlphaTru64 : public Tru64
{
public:
/// This table maps the target open() flags to the corresponding
/// host open() flags.
@ -68,10 +67,10 @@ class AlphaTru64 : public Tru64
//@{
/// For getsysinfo().
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name string
static const unsigned GSI_CPU_INFO = 59; //!< CPU information
static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine
static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
@ -124,6 +123,4 @@ class AlphaTru64 : public Tru64
};
};
#endif
#endif // __ALPHA_ALPHA_TRU64_TRU64_HH__

View file

@ -32,10 +32,9 @@
#ifndef __ARCH_ALPHA_TYPES_HH__
#define __ARCH_ALPHA_TYPES_HH__
#include <inttypes.h>
#include "sim/host.hh"
namespace AlphaISA
{
namespace AlphaISA {
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
@ -51,28 +50,25 @@ namespace AlphaISA
// control register file contents
typedef uint64_t MiscReg;
typedef union {
union AnyReg
{
IntReg intreg;
FloatReg fpreg;
MiscReg ctrlreg;
} AnyReg;
enum RegContextParam
{
CONTEXT_PALMODE
};
typedef bool RegContextVal;
enum annotes {
enum annotes
{
ANNOTE_NONE = 0,
// An impossible number for instruction annotations
ITOUCH_ANNOTE = 0xffffffff,
};
struct CoreSpecific {
struct CoreSpecific
{
int core_type;
};
} // namespace AlphaISA
#endif
#endif // __ARCH_ALPHA_TYPES_HH__

View file

@ -36,28 +36,28 @@
#include "mem/vport.hh"
#endif
namespace AlphaISA
{
namespace AlphaISA {
uint64_t getArgument(ThreadContext *tc, int number, bool fp)
uint64_t
getArgument(ThreadContext *tc, int number, bool fp)
{
#if FULL_SYSTEM
const int NumArgumentRegs = 6;
if (number < NumArgumentRegs) {
if (fp)
return tc->readFloatRegBits(ArgumentReg[number]);
return tc->readFloatRegBits(16 + number);
else
return tc->readIntReg(ArgumentReg[number]);
return tc->readIntReg(16 + number);
} else {
Addr sp = tc->readIntReg(StackPointerReg);
VirtualPort *vp = tc->getVirtPort(tc);
VirtualPort *vp = tc->getVirtPort();
uint64_t arg = vp->read<uint64_t>(sp +
(number-NumArgumentRegs) * sizeof(uint64_t));
tc->delVirtPort(vp);
return arg;
}
#else
panic("getArgument() is Full system only\n");
M5_DUMMY_RETURN
M5_DUMMY_RETURN;
#endif
}

View file

@ -32,76 +32,88 @@
#ifndef __ARCH_ALPHA_UTILITY_HH__
#define __ARCH_ALPHA_UTILITY_HH__
#include "config/full_system.hh"
#include "arch/alpha/types.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/regfile.hh"
#include "base/misc.hh"
#include "config/full_system.hh"
#include "cpu/thread_context.hh"
namespace AlphaISA
{
namespace AlphaISA {
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
static inline bool
inline bool
inUserMode(ThreadContext *tc)
{
return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
return (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
}
inline bool isCallerSaveIntegerRegister(unsigned int reg) {
inline bool
isCallerSaveIntegerRegister(unsigned int reg)
{
panic("register classification not implemented");
return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
return (reg >= 1 && reg <= 8) || (reg >= 22 && reg <= 25) || reg == 27;
}
inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
inline bool
isCalleeSaveIntegerRegister(unsigned int reg)
{
panic("register classification not implemented");
return (reg >= 9 && reg <= 15);
return reg >= 9 && reg <= 15;
}
inline bool isCallerSaveFloatRegister(unsigned int reg) {
inline bool
isCallerSaveFloatRegister(unsigned int reg)
{
panic("register classification not implemented");
return false;
}
inline bool isCalleeSaveFloatRegister(unsigned int reg) {
inline bool
isCalleeSaveFloatRegister(unsigned int reg)
{
panic("register classification not implemented");
return false;
}
inline Addr alignAddress(const Addr &addr,
unsigned int nbytes) {
inline Addr
alignAddress(const Addr &addr, unsigned int nbytes)
{
return (addr & ~(nbytes - 1));
}
// Instruction address compression hooks
inline Addr realPCToFetchPC(const Addr &addr) {
inline Addr
realPCToFetchPC(const Addr &addr)
{
return addr;
}
inline Addr fetchPCToRealPC(const Addr &addr) {
inline Addr
fetchPCToRealPC(const Addr &addr)
{
return addr;
}
// the size of "fetched" instructions (not necessarily the size
// of real instructions for PISA)
inline size_t fetchInstSize() {
inline size_t
fetchInstSize()
{
return sizeof(MachInst);
}
inline MachInst makeRegisterCopy(int dest, int src) {
inline MachInst
makeRegisterCopy(int dest, int src)
{
panic("makeRegisterCopy not implemented");
return 0;
}
// Machine operations
void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
int regnum);
void restoreMachineReg(RegFile &regs, const AnyReg &reg,
int regnum);
void saveMachineReg(AnyReg &savereg, const RegFile &reg_file, int regnum);
void restoreMachineReg(RegFile &regs, const AnyReg &reg, int regnum);
/**
* Function to insure ISA semantics about 0 registers.
@ -112,9 +124,7 @@ namespace AlphaISA
// Alpha IPR register accessors
inline bool PcPAL(Addr addr) { return addr & 0x3; }
inline void startupCPU(ThreadContext *tc, int cpuId) {
tc->activate(0);
}
inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); }
////////////////////////////////////////////////////////////////////////
//
@ -155,4 +165,4 @@ namespace AlphaISA
} // namespace AlphaISA
#endif
#endif // __ARCH_ALPHA_UTILITY_HH__

View file

@ -40,27 +40,28 @@
#include "mem/vport.hh"
using namespace std;
using namespace AlphaISA;
AlphaISA::PageTableEntry
AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr)
namespace AlphaISA {
PageTableEntry
kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, VAddr vaddr)
{
Addr level1_pte = ptbr + vaddr.level1();
AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte);
PageTableEntry level1 = mem->read<uint64_t>(level1_pte);
if (!level1.valid()) {
DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
return 0;
}
Addr level2_pte = level1.paddr() + vaddr.level2();
AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte);
PageTableEntry level2 = mem->read<uint64_t>(level2_pte);
if (!level2.valid()) {
DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
return 0;
}
Addr level3_pte = level2.paddr() + vaddr.level3();
AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte);
PageTableEntry level3 = mem->read<uint64_t>(level3_pte);
if (!level3.valid()) {
DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
return 0;
@ -69,13 +70,13 @@ AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vadd
}
Addr
AlphaISA::vtophys(Addr vaddr)
vtophys(Addr vaddr)
{
Addr paddr = 0;
if (AlphaISA::IsUSeg(vaddr))
if (IsUSeg(vaddr))
DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
else if (AlphaISA::IsK0Seg(vaddr))
paddr = AlphaISA::K0Seg2Phys(vaddr);
else if (IsK0Seg(vaddr))
paddr = K0Seg2Phys(vaddr);
else
panic("vtophys: ptbr is not set on virtual lookup");
@ -85,22 +86,22 @@ AlphaISA::vtophys(Addr vaddr)
}
Addr
AlphaISA::vtophys(ThreadContext *tc, Addr addr)
vtophys(ThreadContext *tc, Addr addr)
{
AlphaISA::VAddr vaddr = addr;
Addr ptbr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20);
VAddr vaddr = addr;
Addr ptbr = tc->readMiscRegNoEffect(IPR_PALtemp20);
Addr paddr = 0;
//@todo Andrew couldn't remember why he commented some of this code
//so I put it back in. Perhaps something to do with gdb debugging?
if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
if (PcPAL(vaddr) && (vaddr < PalMax)) {
paddr = vaddr & ~ULL(1);
} else {
if (AlphaISA::IsK0Seg(vaddr)) {
paddr = AlphaISA::K0Seg2Phys(vaddr);
if (IsK0Seg(vaddr)) {
paddr = K0Seg2Phys(vaddr);
} else if (!ptbr) {
paddr = vaddr;
} else {
AlphaISA::PageTableEntry pte =
PageTableEntry pte =
kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr);
if (pte.valid())
paddr = pte.paddr() | vaddr.offset();
@ -113,3 +114,4 @@ AlphaISA::vtophys(ThreadContext *tc, Addr addr)
return paddr;
}
} // namespace AlphaISA

View file

@ -41,12 +41,13 @@ class FunctionalPort;
namespace AlphaISA {
PageTableEntry
kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr);
PageTableEntry kernel_pte_lookup(FunctionalPort *mem, Addr ptbr,
VAddr vaddr);
Addr vtophys(Addr vaddr);
Addr vtophys(ThreadContext *tc, Addr vaddr);
};
} // namespace AlphaISA
#endif // __ARCH_ALPHA_VTOPHYS_H__

View file

@ -34,25 +34,21 @@ from m5.params import *
class ArmTLB(SimObject):
abstract = True
type = 'ArmTLB'
cxx_namespace = 'ArmISA'
cxx_class = 'TLB'
cxx_class = 'ArmISA::TLB'
size = Param.Int("TLB size")
class ArmDTB(ArmTLB):
type = 'ArmDTB'
cxx_namespace = 'ArmISA'
cxx_class = 'DTB'
cxx_class = 'ArmISA::DTB'
size = 64
class ArmITB(ArmTLB):
type = 'ArmITB'
cxx_namespace = 'ArmISA'
cxx_class = 'ITB'
cxx_class = 'ArmISA::ITB'
size = 64
class ArmUTB(ArmTLB):
type = 'ArmUTB'
cxx_namespace = 'ArmISA'
cxx_class = 'UTB'
cxx_class = 'ArmISA::UTB'
size = 64

View file

@ -131,9 +131,6 @@ namespace ArmISA
const int ZeroReg = NumIntArchRegs;
const int AddrReg = ZeroReg + 1; // Used to generate address for uops
const int ArgumentReg[] = {0, 1, 2, 3};
const int NumArgumentRegs = sizeof(ArgumentReg)/ sizeof(const int);
const int SyscallNumReg = ReturnValueReg;
const int SyscallPseudoReturnReg = ReturnValueReg;
const int SyscallSuccessReg = ReturnValueReg;

View file

@ -49,7 +49,7 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0));
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
strcpy(name->sysname, "Linux");
strcpy(name->nodename, "m5.eecs.umich.edu");
@ -79,7 +79,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 14 */ SyscallDesc("mknod", unimplementedFunc),
/* 15 */ SyscallDesc("chmod", chmodFunc<ArmLinux>),
/* 16 */ SyscallDesc("lchown", chownFunc),
/* 17 */ SyscallDesc("break", obreakFunc), //???
/* 17 */ SyscallDesc("break", brkFunc), //???
/* 18 */ SyscallDesc("unused#18", unimplementedFunc), //???
/* 19 */ SyscallDesc("lseek", lseekFunc),
/* 20 */ SyscallDesc("getpid", getpidFunc),
@ -107,7 +107,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 42 */ SyscallDesc("pipe", unimplementedFunc),
/* 43 */ SyscallDesc("times", unimplementedFunc),
/* 44 */ SyscallDesc("prof", unimplementedFunc),
/* 45 */ SyscallDesc("brk", obreakFunc),
/* 45 */ SyscallDesc("brk", brkFunc),
/* 46 */ SyscallDesc("setgid", unimplementedFunc),
/* 47 */ SyscallDesc("getgid", getgidFunc),
/* 48 */ SyscallDesc("signal", ignoreFunc),

View file

@ -43,8 +43,7 @@
using namespace std;
using namespace ArmISA;
ArmLiveProcess::ArmLiveProcess(LiveProcessParams * params,
ObjectFile *objFile)
ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile)
: LiveProcess(params, objFile)
{
stack_base = 0xc0000000L;
@ -147,12 +146,35 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
initVirtMem->writeBlob(0xffff0fe0, insns, 8);
*/
threadContexts[0]->setIntReg(ArgumentReg1, argc);
threadContexts[0]->setIntReg(ArgumentReg2, argv_array_base);
threadContexts[0]->setIntReg(StackPointerReg, stack_min);
ThreadContext *tc = system->getThreadContext(contextIds[0]);
tc->setIntReg(ArgumentReg1, argc);
tc->setIntReg(ArgumentReg2, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
Addr prog_entry = objFile->entryPoint();
threadContexts[0]->setPC(prog_entry);
threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
tc->setPC(prog_entry);
tc->setNextPC(prog_entry + sizeof(MachInst));
}
ArmISA::IntReg
ArmLiveProcess::getSyscallArg(ThreadContext *tc, int i)
{
assert(i < 4);
return tc->readIntReg(ArgumentReg0 + i);
}
void
ArmLiveProcess::setSyscallArg(ThreadContext *tc,
int i, ArmISA::IntReg val)
{
assert(i < 4);
tc->setIntReg(ArgumentReg0 + i, val);
}
void
ArmLiveProcess::setSyscallReturn(ThreadContext *tc,
SyscallReturn return_value)
{
tc->setIntReg(ReturnValueReg, return_value.value());
}

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