Merge ARM into the head. ARM will compile but may not actually work.
This commit is contained in:
commit
d080581db1
1238 changed files with 77272 additions and 36447 deletions
2
.hgtags
2
.hgtags
|
@ -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
2
README
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
--------------------
|
||||
|
|
675
SConstruct
675
SConstruct
|
@ -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)
|
||||
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)
|
||||
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:
|
||||
subp = Popen(cmd, **kwargs)
|
||||
except Exception, e:
|
||||
if no_exception:
|
||||
return exception
|
||||
raise
|
||||
|
||||
# The absolute path to the current directory (where this file lives).
|
||||
ROOT = Dir('.').abspath
|
||||
return subp.communicate()[0]
|
||||
|
||||
# Path to the M5 source tree.
|
||||
SRCDIR = joinpath(ROOT, 'src')
|
||||
# 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
|
||||
|
||||
# tell python where to find m5 python code
|
||||
sys.path.append(joinpath(ROOT, 'src/python'))
|
||||
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
|
||||
|
||||
def check_style_hook(ui):
|
||||
ui.readconfig(joinpath(ROOT, '.hg', 'hgrc'))
|
||||
style_hook = ui.config('hooks', 'pretxncommit.style', None)
|
||||
########################################################################
|
||||
#
|
||||
# Set up the base build environment.
|
||||
#
|
||||
########################################################################
|
||||
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH',
|
||||
'RANLIB' ])
|
||||
|
||||
if not style_hook:
|
||||
print """\
|
||||
use_env = {}
|
||||
for key,val in os.environ.iteritems():
|
||||
if key in use_vars or key.startswith("M5"):
|
||||
use_env[key] = val
|
||||
|
||||
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,28 +296,17 @@ 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')
|
||||
|
||||
env.SConsignFile(joinpath(build_root,"sconsign"))
|
||||
env.SConsignFile(joinpath(build_root, "sconsign"))
|
||||
|
||||
# Default duplicate option is to use hard links, but this messes up
|
||||
# when you use emacs to edit a file in the target dir, as emacs moves
|
||||
|
@ -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']:
|
||||
|
@ -323,16 +403,24 @@ elif env['SUNCC']:
|
|||
env.Append(CCFLAGS='-features=extensions')
|
||||
env.Append(CCFLAGS='-library=stlport4')
|
||||
env.Append(CCFLAGS='-xar')
|
||||
# env.Append(CCFLAGS='-instances=semiexplicit')
|
||||
#env.Append(CCFLAGS='-instances=semiexplicit')
|
||||
else:
|
||||
print 'Error: Don\'t know what compiler options to use for your compiler.'
|
||||
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.
|
||||
#
|
||||
###################################################
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
504
ext/gzstream/LICENSE
Normal 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
38
ext/gzstream/SConscript
Normal 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
1
ext/gzstream/VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
1.5 (08 Jan 2003)
|
165
ext/gzstream/gzstream.cc
Normal file
165
ext/gzstream/gzstream.cc
Normal 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
122
ext/gzstream/gzstream.hh
Normal 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 //
|
||||
|
|
@ -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'])
|
||||
|
|
795
src/SConscript
795
src/SConscript
|
@ -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,17 +209,24 @@ 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):
|
||||
here = Dir('.').srcnode().abspath
|
||||
for root, dirs, files in os.walk(base_dir, topdown=True):
|
||||
if root == here:
|
||||
# we don't want to recurse back into this SConscript
|
||||
continue
|
||||
|
@ -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 = {}
|
||||
|
|
|
@ -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' ])
|
||||
|
|
33
src/arch/alpha/AlphaInterrupts.py
Normal file
33
src/arch/alpha/AlphaInterrupts.py
Normal 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'
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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,12 +176,13 @@ void ItbFault::invoke(ThreadContext * tc)
|
|||
|
||||
#else
|
||||
|
||||
void ItbPageFault::invoke(ThreadContext * tc)
|
||||
void
|
||||
ItbPageFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
Process *p = tc->getProcessPtr();
|
||||
TlbEntry entry;
|
||||
bool success = p->pTable->lookup(pc, entry);
|
||||
if(!success) {
|
||||
if (!success) {
|
||||
panic("Tried to execute unmapped address %#x.\n", pc);
|
||||
} else {
|
||||
VAddr vaddr(pc);
|
||||
|
@ -187,16 +190,17 @@ void ItbPageFault::invoke(ThreadContext * tc)
|
|||
}
|
||||
}
|
||||
|
||||
void NDtbMissFault::invoke(ThreadContext * tc)
|
||||
void
|
||||
NDtbMissFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
Process *p = tc->getProcessPtr();
|
||||
TlbEntry entry;
|
||||
bool success = p->pTable->lookup(vaddr, entry);
|
||||
if(!success) {
|
||||
if (!success) {
|
||||
p->checkAndAllocNextPage(vaddr);
|
||||
success = p->pTable->lookup(vaddr, entry);
|
||||
}
|
||||
if(!success) {
|
||||
if (!success) {
|
||||
panic("Tried to access unmapped address %#x.\n", (Addr)vaddr);
|
||||
} else {
|
||||
tc->getDTBPtr()->insert(vaddr.page(), entry);
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -30,20 +30,28 @@
|
|||
* Kevin Lim
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "arch/alpha/floatregfile.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
namespace AlphaISA
|
||||
namespace AlphaISA {
|
||||
void
|
||||
FloatRegFile::clear()
|
||||
{
|
||||
void
|
||||
FloatRegFile::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ARRAY(q, NumFloatRegs);
|
||||
}
|
||||
|
||||
void
|
||||
FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ARRAY(q, NumFloatRegs);
|
||||
}
|
||||
std::memset(d, 0, sizeof(d));
|
||||
}
|
||||
|
||||
void
|
||||
FloatRegFile::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ARRAY(q, NumFloatRegs);
|
||||
}
|
||||
|
||||
void
|
||||
FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ARRAY(q, NumFloatRegs);
|
||||
}
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
|
|
@ -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
|
||||
namespace AlphaISA {
|
||||
|
||||
class FloatRegFile
|
||||
{
|
||||
static inline std::string getFloatRegName(RegIndex)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
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 §ion);
|
||||
};
|
||||
|
||||
void clear()
|
||||
{ std::memset(d, 0, sizeof(d)); }
|
||||
};
|
||||
}
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif
|
||||
#endif // __ARCH_ALPHA_FLOATREGFILE_HH__
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -57,7 +57,6 @@ class FreebsdAlphaSystem : public AlphaSystem
|
|||
~FreebsdAlphaSystem();
|
||||
|
||||
void doCalibrateClocks(ThreadContext *tc);
|
||||
|
||||
};
|
||||
|
||||
#endif // __ARCH_ALPHA_FREEBSD_SYSTEM_HH__
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
12
src/cpu/o3/sparc/thread_context.cc → src/arch/alpha/interrupts.cc
Executable file → Normal file
12
src/cpu/o3/sparc/thread_context.cc → src/arch/alpha/interrupts.cc
Executable file → Normal 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);
|
||||
}
|
|
@ -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
|
||||
namespace AlphaISA {
|
||||
|
||||
class Interrupts : public SimObject
|
||||
{
|
||||
class Interrupts
|
||||
{
|
||||
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 §ion)
|
||||
void
|
||||
unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
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
|
||||
}
|
||||
} // namespace AlphaISA
|
||||
|
||||
private:
|
||||
bool newInfoSet;
|
||||
int newIpl;
|
||||
int newSummary;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // __ARCH_ALPHA_INTERRUPT_HH__
|
||||
|
||||
|
|
|
@ -30,36 +30,45 @@
|
|||
* 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::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ARRAY(regs, NumIntRegs);
|
||||
}
|
||||
|
||||
void
|
||||
IntRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ARRAY(regs, NumIntRegs);
|
||||
}
|
||||
void
|
||||
IntRegFile::clear()
|
||||
{
|
||||
std::memset(regs, 0, sizeof(regs));
|
||||
}
|
||||
|
||||
void
|
||||
IntRegFile::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ARRAY(regs, NumIntRegs);
|
||||
}
|
||||
|
||||
void
|
||||
IntRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ARRAY(regs, NumIntRegs);
|
||||
}
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
|
|
|
@ -32,47 +32,42 @@
|
|||
#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
|
||||
namespace AlphaISA {
|
||||
|
||||
// redirected register map, really only used for the full system case.
|
||||
extern const int reg_redir[NumIntRegs];
|
||||
|
||||
class IntRegFile
|
||||
{
|
||||
static inline std::string getIntRegName(RegIndex)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// redirected register map, really only used for the full system case.
|
||||
extern const int reg_redir[NumIntRegs];
|
||||
|
||||
class IntRegFile
|
||||
{
|
||||
protected:
|
||||
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 §ion);
|
||||
};
|
||||
|
||||
void clear()
|
||||
{ std::memset(regs, 0, sizeof(regs)); }
|
||||
};
|
||||
}
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif
|
||||
#endif // __ARCH_ALPHA_INTREGFILE_HH__
|
||||
|
|
|
@ -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
|
||||
|
@ -121,20 +121,22 @@ namespace AlphaISA
|
|||
RAW_IPR_DC_TEST_TAG_TEMP, // Dcache test tag temporary register
|
||||
RAW_IPR_DC_MODE, // Dcache mode register
|
||||
RAW_IPR_MAF_MODE // miss address file mode register
|
||||
};
|
||||
};
|
||||
|
||||
int IprToMiscRegIndex[MaxInternalProcRegs];
|
||||
int IprToMiscRegIndex[MaxInternalProcRegs];
|
||||
|
||||
void initializeIprTable()
|
||||
{
|
||||
void
|
||||
initializeIprTable()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if(initialized)
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
memset(IprToMiscRegIndex, -1, MaxInternalProcRegs * sizeof(int));
|
||||
|
||||
for(int x = 0; x < NumInternalProcRegs; x++)
|
||||
for (int x = 0; x < NumInternalProcRegs; x++)
|
||||
IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
|
|
|
@ -32,41 +32,40 @@
|
|||
#ifndef __ARCH_ALPHA_IPR_HH__
|
||||
#define __ARCH_ALPHA_IPR_HH__
|
||||
|
||||
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
|
||||
namespace AlphaISA {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Internal Processor Reigsters
|
||||
//
|
||||
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,37 +94,37 @@ 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
|
||||
{
|
||||
enum MiscRegIpr
|
||||
{
|
||||
//Write only
|
||||
MinWriteOnlyIpr,
|
||||
IPR_HWINT_CLR = MinWriteOnlyIpr,
|
||||
|
@ -216,22 +215,25 @@ namespace AlphaISA
|
|||
IPR_MAF_MODE,
|
||||
|
||||
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)
|
||||
{
|
||||
return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr;
|
||||
}
|
||||
|
||||
extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs];
|
||||
extern int IprToMiscRegIndex[MaxInternalProcRegs];
|
||||
|
||||
void initializeIprTable();
|
||||
}
|
||||
|
||||
#endif
|
||||
inline bool
|
||||
IprIsReadable(int index)
|
||||
{
|
||||
return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr;
|
||||
}
|
||||
|
||||
extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs];
|
||||
extern int IprToMiscRegIndex[MaxInternalProcRegs];
|
||||
|
||||
void initializeIprTable();
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ARCH_ALPHA_IPR_HH__
|
||||
|
|
|
@ -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();
|
||||
1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore);
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,64 +42,61 @@ namespace LittleEndianGuest {}
|
|||
|
||||
class StaticInstPtr;
|
||||
|
||||
namespace AlphaISA
|
||||
{
|
||||
using namespace LittleEndianGuest;
|
||||
using AlphaISAInst::MaxInstSrcRegs;
|
||||
using AlphaISAInst::MaxInstDestRegs;
|
||||
namespace AlphaISA {
|
||||
|
||||
// These enumerate all the registers for dependence tracking.
|
||||
enum DependenceTags {
|
||||
using namespace LittleEndianGuest;
|
||||
using AlphaISAInst::MaxInstSrcRegs;
|
||||
using AlphaISAInst::MaxInstDestRegs;
|
||||
|
||||
// These enumerate all the registers for dependence tracking.
|
||||
enum DependenceTags {
|
||||
// 0..31 are the integer regs 0..31
|
||||
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
|
||||
FP_Base_DepTag = 40,
|
||||
Ctrl_Base_DepTag = 72
|
||||
};
|
||||
};
|
||||
|
||||
StaticInstPtr decodeInst(ExtMachInst);
|
||||
StaticInstPtr decodeInst(ExtMachInst);
|
||||
|
||||
// Alpha Does NOT have a delay slot
|
||||
#define ISA_HAS_DELAY_SLOT 0
|
||||
// Alpha Does NOT have a delay slot
|
||||
#define ISA_HAS_DELAY_SLOT 0
|
||||
|
||||
const Addr PageShift = 13;
|
||||
const Addr PageBytes = ULL(1) << PageShift;
|
||||
const Addr PageMask = ~(PageBytes - 1);
|
||||
const Addr PageOffset = PageBytes - 1;
|
||||
const Addr PageShift = 13;
|
||||
const Addr PageBytes = ULL(1) << PageShift;
|
||||
const Addr PageMask = ~(PageBytes - 1);
|
||||
const Addr PageOffset = PageBytes - 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Translation stuff
|
||||
//
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Translation stuff
|
||||
//
|
||||
const Addr PteShift = 3;
|
||||
const Addr NPtePageShift = PageShift - PteShift;
|
||||
const Addr NPtePage = ULL(1) << NPtePageShift;
|
||||
const Addr PteMask = NPtePage - 1;
|
||||
|
||||
const Addr PteShift = 3;
|
||||
const Addr NPtePageShift = PageShift - PteShift;
|
||||
const Addr NPtePage = ULL(1) << NPtePageShift;
|
||||
const Addr PteMask = NPtePage - 1;
|
||||
// User Virtual
|
||||
const Addr USegBase = ULL(0x0);
|
||||
const Addr USegEnd = ULL(0x000003ffffffffff);
|
||||
|
||||
// User Virtual
|
||||
const Addr USegBase = ULL(0x0);
|
||||
const Addr USegEnd = ULL(0x000003ffffffffff);
|
||||
// Kernel Direct Mapped
|
||||
const Addr K0SegBase = ULL(0xfffffc0000000000);
|
||||
const Addr K0SegEnd = ULL(0xfffffdffffffffff);
|
||||
|
||||
// Kernel Direct Mapped
|
||||
const Addr K0SegBase = ULL(0xfffffc0000000000);
|
||||
const Addr K0SegEnd = ULL(0xfffffdffffffffff);
|
||||
// Kernel Virtual
|
||||
const Addr K1SegBase = ULL(0xfffffe0000000000);
|
||||
const Addr K1SegEnd = ULL(0xffffffffffffffff);
|
||||
|
||||
// Kernel Virtual
|
||||
const Addr K1SegBase = ULL(0xfffffe0000000000);
|
||||
const Addr K1SegEnd = ULL(0xffffffffffffffff);
|
||||
// For loading... XXX This maybe could be USegEnd?? --ali
|
||||
const Addr LoadAddrMask = ULL(0xffffffffff);
|
||||
|
||||
// For loading... XXX This maybe could be USegEnd?? --ali
|
||||
const Addr LoadAddrMask = ULL(0xffffffffff);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Interrupt levels
|
||||
//
|
||||
enum InterruptLevels
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Interrupt levels
|
||||
//
|
||||
enum InterruptLevels
|
||||
{
|
||||
INTLEVEL_SOFTWARE_MIN = 4,
|
||||
INTLEVEL_SOFTWARE_MAX = 19,
|
||||
|
||||
|
@ -116,68 +113,63 @@ namespace AlphaISA
|
|||
INTLEVEL_SERIAL = 33,
|
||||
|
||||
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// EV5 modes
|
||||
enum mode_type
|
||||
{
|
||||
// EV5 modes
|
||||
enum mode_type
|
||||
{
|
||||
mode_kernel = 0, // kernel
|
||||
mode_executive = 1, // executive (unused by unix)
|
||||
mode_supervisor = 2, // supervisor (unused by unix)
|
||||
mode_user = 3, // user mode
|
||||
mode_number // number of modes
|
||||
};
|
||||
|
||||
// Constants Related to the number of registers
|
||||
|
||||
const int NumIntArchRegs = 32;
|
||||
const int NumPALShadowRegs = 8;
|
||||
const int NumFloatArchRegs = 32;
|
||||
// @todo: Figure out what this number really should be.
|
||||
const int NumMiscArchRegs = 77;
|
||||
|
||||
const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs;
|
||||
const int NumFloatRegs = NumFloatArchRegs;
|
||||
const int NumMiscRegs = NumMiscArchRegs;
|
||||
|
||||
const int TotalNumRegs = NumIntRegs + NumFloatRegs +
|
||||
NumMiscRegs + NumInternalProcRegs;
|
||||
|
||||
const int TotalDataRegs = NumIntRegs + NumFloatRegs;
|
||||
|
||||
// semantically meaningful register indices
|
||||
const int ZeroReg = 31; // architecturally meaningful
|
||||
// the rest of these depend on the ABI
|
||||
const int StackPointerReg = 30;
|
||||
const int GlobalPointerReg = 29;
|
||||
const int ProcedureValueReg = 27;
|
||||
const int ReturnAddressReg = 26;
|
||||
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 LogVMPageSize = 13; // 8K bytes
|
||||
const int VMPageSize = (1 << LogVMPageSize);
|
||||
|
||||
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
|
||||
|
||||
const int MachineBytes = 8;
|
||||
const int WordBytes = 4;
|
||||
const int HalfwordBytes = 2;
|
||||
const int ByteBytes = 1;
|
||||
|
||||
// return a no-op instruction... used for instruction fetch faults
|
||||
// Alpha UNOP (ldq_u r31,0(r0))
|
||||
const ExtMachInst NoopMachInst = 0x2ffe0000;
|
||||
|
||||
};
|
||||
|
||||
// Constants Related to the number of registers
|
||||
|
||||
const int NumIntArchRegs = 32;
|
||||
const int NumPALShadowRegs = 8;
|
||||
const int NumFloatArchRegs = 32;
|
||||
// @todo: Figure out what this number really should be.
|
||||
const int NumMiscArchRegs = 77;
|
||||
|
||||
const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs;
|
||||
const int NumFloatRegs = NumFloatArchRegs;
|
||||
const int NumMiscRegs = NumMiscArchRegs;
|
||||
|
||||
const int TotalNumRegs =
|
||||
NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs;
|
||||
|
||||
const int TotalDataRegs = NumIntRegs + NumFloatRegs;
|
||||
|
||||
// semantically meaningful register indices
|
||||
const int ZeroReg = 31; // architecturally meaningful
|
||||
// the rest of these depend on the ABI
|
||||
const int StackPointerReg = 30;
|
||||
const int GlobalPointerReg = 29;
|
||||
const int ProcedureValueReg = 27;
|
||||
const int ReturnAddressReg = 26;
|
||||
const int ReturnValueReg = 0;
|
||||
const int FramePointerReg = 15;
|
||||
|
||||
const int SyscallNumReg = 0;
|
||||
const int FirstArgumentReg = 16;
|
||||
const int SyscallPseudoReturnReg = 20;
|
||||
|
||||
const int LogVMPageSize = 13; // 8K bytes
|
||||
const int VMPageSize = (1 << LogVMPageSize);
|
||||
|
||||
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
|
||||
|
||||
const int MachineBytes = 8;
|
||||
const int WordBytes = 4;
|
||||
const int HalfwordBytes = 2;
|
||||
const int ByteBytes = 1;
|
||||
|
||||
// return a no-op instruction... used for instruction fetch faults
|
||||
// Alpha UNOP (ldq_u r31,0(r0))
|
||||
const ExtMachInst NoopMachInst = 0x2ffe0000;
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ARCH_ALPHA_ISA_TRAITS_HH__
|
||||
|
|
|
@ -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 §ion)
|
|||
themode = (cpu_mode)exemode;
|
||||
}
|
||||
|
||||
} /* end namespace AlphaISA::Kernel */
|
||||
} /* end namespace AlphaISA */
|
||||
} // namespace Kernel
|
||||
} // namespace AlphaISA
|
||||
|
|
|
@ -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 §ion);
|
||||
};
|
||||
|
||||
} /* end namespace AlphaISA::Kernel */
|
||||
} /* end namespace AlphaISA */
|
||||
} // namespace Kernel
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ARCH_ALPHA_KERNEL_STATS_HH__
|
||||
|
|
|
@ -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]));
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -51,4 +51,5 @@ class AlphaLinuxProcess : public AlphaLiveProcess
|
|||
};
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ALPHA_LINUX_PROCESS_HH__
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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__
|
||||
|
|
41
src/arch/alpha/microcode_rom.hh
Normal file
41
src/arch/alpha/microcode_rom.hh
Normal 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__
|
|
@ -30,36 +30,37 @@
|
|||
* Kevin Lim
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "arch/alpha/miscregfile.hh"
|
||||
#include "base/misc.hh"
|
||||
|
||||
namespace AlphaISA
|
||||
{
|
||||
namespace AlphaISA {
|
||||
|
||||
void
|
||||
MiscRegFile::serialize(std::ostream &os)
|
||||
{
|
||||
void
|
||||
MiscRegFile::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(fpcr);
|
||||
SERIALIZE_SCALAR(uniq);
|
||||
SERIALIZE_SCALAR(lock_flag);
|
||||
SERIALIZE_SCALAR(lock_addr);
|
||||
SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
void
|
||||
MiscRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(fpcr);
|
||||
UNSERIALIZE_SCALAR(uniq);
|
||||
UNSERIALIZE_SCALAR(lock_flag);
|
||||
UNSERIALIZE_SCALAR(lock_addr);
|
||||
UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
|
||||
}
|
||||
}
|
||||
|
||||
MiscReg
|
||||
MiscRegFile::readRegNoEffect(int misc_reg)
|
||||
{
|
||||
switch(misc_reg) {
|
||||
MiscReg
|
||||
MiscRegFile::readRegNoEffect(int misc_reg)
|
||||
{
|
||||
switch (misc_reg) {
|
||||
case MISCREG_FPCR:
|
||||
return fpcr;
|
||||
case MISCREG_UNIQ:
|
||||
|
@ -74,12 +75,12 @@ namespace AlphaISA
|
|||
assert(misc_reg < NumInternalProcRegs);
|
||||
return ipr[misc_reg];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MiscReg
|
||||
MiscRegFile::readReg(int misc_reg, ThreadContext *tc)
|
||||
{
|
||||
switch(misc_reg) {
|
||||
MiscReg
|
||||
MiscRegFile::readReg(int misc_reg, ThreadContext *tc)
|
||||
{
|
||||
switch (misc_reg) {
|
||||
case MISCREG_FPCR:
|
||||
return fpcr;
|
||||
case MISCREG_UNIQ:
|
||||
|
@ -93,12 +94,12 @@ namespace AlphaISA
|
|||
default:
|
||||
return readIpr(misc_reg, tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val)
|
||||
{
|
||||
switch(misc_reg) {
|
||||
void
|
||||
MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val)
|
||||
{
|
||||
switch (misc_reg) {
|
||||
case MISCREG_FPCR:
|
||||
fpcr = val;
|
||||
return;
|
||||
|
@ -119,13 +120,12 @@ namespace AlphaISA
|
|||
ipr[misc_reg] = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::setReg(int misc_reg, const MiscReg &val,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
switch(misc_reg) {
|
||||
void
|
||||
MiscRegFile::setReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||
{
|
||||
switch (misc_reg) {
|
||||
case MISCREG_FPCR:
|
||||
fpcr = val;
|
||||
return;
|
||||
|
@ -145,6 +145,6 @@ namespace AlphaISA
|
|||
setIpr(misc_reg, val, tc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
|
|
@ -32,33 +32,33 @@
|
|||
#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
|
||||
{
|
||||
enum MiscRegIndex
|
||||
{
|
||||
MISCREG_FPCR = NumInternalProcRegs,
|
||||
MISCREG_UNIQ,
|
||||
MISCREG_LOCKFLAG,
|
||||
MISCREG_LOCKADDR,
|
||||
MISCREG_INTR
|
||||
};
|
||||
};
|
||||
|
||||
static inline std::string getMiscRegName(RegIndex)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
class MiscRegFile
|
||||
{
|
||||
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 §ion);
|
||||
protected:
|
||||
typedef uint64_t InternalProcReg;
|
||||
};
|
||||
|
||||
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
|
||||
void copyIprs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
private:
|
||||
InternalProcReg readIpr(int idx, ThreadContext *tc);
|
||||
} // namespace AlphaISA
|
||||
|
||||
void setIpr(int idx, InternalProcReg val, ThreadContext *tc);
|
||||
friend class RegFile;
|
||||
};
|
||||
|
||||
void copyIprs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // __ARCH_ALPHA_MISCREGFILE_HH__
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -31,11 +31,11 @@
|
|||
#include "arch/alpha/pagetable.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
namespace AlphaISA
|
||||
namespace AlphaISA {
|
||||
|
||||
void
|
||||
TlbEntry::serialize(std::ostream &os)
|
||||
{
|
||||
void
|
||||
TlbEntry::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(tag);
|
||||
SERIALIZE_SCALAR(ppn);
|
||||
SERIALIZE_SCALAR(xre);
|
||||
|
@ -45,11 +45,11 @@ namespace AlphaISA
|
|||
SERIALIZE_SCALAR(fonr);
|
||||
SERIALIZE_SCALAR(fonw);
|
||||
SERIALIZE_SCALAR(valid);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TlbEntry::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
void
|
||||
TlbEntry::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(tag);
|
||||
UNSERIALIZE_SCALAR(ppn);
|
||||
UNSERIALIZE_SCALAR(xre);
|
||||
|
@ -59,5 +59,6 @@ namespace AlphaISA
|
|||
UNSERIALIZE_SCALAR(fonr);
|
||||
UNSERIALIZE_SCALAR(fonw);
|
||||
UNSERIALIZE_SCALAR(valid);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace AlphaISA
|
||||
|
|
|
@ -38,14 +38,15 @@
|
|||
|
||||
namespace AlphaISA {
|
||||
|
||||
struct VAddr
|
||||
{
|
||||
struct VAddr
|
||||
{
|
||||
static const int ImplBits = 43;
|
||||
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,15 +55,15 @@ 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
|
||||
{
|
||||
struct PageTableEntry
|
||||
{
|
||||
PageTableEntry(uint64_t e) : entry(e) {}
|
||||
uint64_t entry;
|
||||
operator uint64_t() const { return entry; }
|
||||
|
@ -87,11 +88,22 @@ namespace AlphaISA {
|
|||
bool valid() const { return (entry >> 0) & 0x1; }
|
||||
|
||||
Addr paddr() const { return _pfn() << PageShift; }
|
||||
};
|
||||
};
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
// ITB/DTB table entry
|
||||
struct TlbEntry
|
||||
{
|
||||
//Construct an entry that maps to physical address addr.
|
||||
TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr)
|
||||
{
|
||||
|
@ -107,28 +119,28 @@ 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;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ARCH_ALPHA_PAGETABLE_H__
|
||||
|
||||
|
|
|
@ -38,62 +38,72 @@
|
|||
|
||||
class ThreadContext;
|
||||
|
||||
namespace AlphaISA
|
||||
namespace AlphaISA {
|
||||
|
||||
class Predecoder
|
||||
{
|
||||
class Predecoder
|
||||
{
|
||||
protected:
|
||||
ThreadContext * tc;
|
||||
//The extended machine instruction being generated
|
||||
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)
|
||||
// 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)
|
||||
{
|
||||
ext_inst = inst;
|
||||
#if FULL_SYSTEM
|
||||
ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
|
||||
ext_inst |= (static_cast<ExtMachInst>(pc & 0x1) << 32);
|
||||
#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()
|
||||
// This returns a constant reference to the ExtMachInst to avoid a copy
|
||||
const ExtMachInst &
|
||||
getExtMachInst()
|
||||
{
|
||||
return ext_inst;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ARCH_ALPHA_PREDECODER_HH__
|
||||
|
|
|
@ -32,15 +32,19 @@
|
|||
#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;
|
||||
|
||||
AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams * params,
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
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__
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
#include "arch/alpha/regfile.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
|
||||
namespace AlphaISA
|
||||
using namespace std;
|
||||
|
||||
namespace AlphaISA {
|
||||
|
||||
void
|
||||
RegFile::serialize(EventManager *em, ostream &os)
|
||||
{
|
||||
void
|
||||
RegFile::serialize(std::ostream &os)
|
||||
{
|
||||
intRegFile.serialize(os);
|
||||
floatRegFile.serialize(os);
|
||||
miscRegFile.serialize(os);
|
||||
|
@ -46,11 +48,11 @@ namespace AlphaISA
|
|||
#if FULL_SYSTEM
|
||||
SERIALIZE_SCALAR(intrflag);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
void
|
||||
RegFile::unserialize(EventManager *em, Checkpoint *cp, const string §ion)
|
||||
{
|
||||
intRegFile.unserialize(cp, section);
|
||||
floatRegFile.unserialize(cp, section);
|
||||
miscRegFile.unserialize(cp, section);
|
||||
|
@ -59,20 +61,18 @@ namespace AlphaISA
|
|||
#if FULL_SYSTEM
|
||||
UNSERIALIZE_SCALAR(intrflag);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||
{
|
||||
void
|
||||
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);
|
||||
|
@ -80,20 +80,21 @@ namespace AlphaISA
|
|||
// Lastly copy PC/NPC
|
||||
dest->setPC(src->readPC());
|
||||
dest->setNextPC(src->readNextPC());
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
void
|
||||
copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
||||
class RegFile {
|
||||
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,116 +95,135 @@ 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 §ion);
|
||||
void serialize(EventManager *em, std::ostream &os);
|
||||
void unserialize(EventManager *em, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
void changeContext(RegContextParam param, RegContextVal val)
|
||||
{
|
||||
//This would be an alternative place to call/implement
|
||||
//the swapPALShadow function
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif
|
||||
#endif // __ARCH_ALPHA_REGFILE_HH__
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -44,18 +44,13 @@ class System;
|
|||
class ThreadContext;
|
||||
class PhysicalMemory;
|
||||
|
||||
namespace AlphaISA
|
||||
namespace AlphaISA {
|
||||
|
||||
class RemoteGDB : public BaseRemoteGDB
|
||||
{
|
||||
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__
|
||||
|
|
|
@ -41,43 +41,39 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
namespace AlphaISA
|
||||
{
|
||||
ProcessInfo::ProcessInfo(ThreadContext *_tc)
|
||||
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
|
||||
ProcessInfo::task(Addr ksp) const
|
||||
{
|
||||
Addr
|
||||
ProcessInfo::task(Addr ksp) const
|
||||
{
|
||||
Addr base = ksp & ~0x3fff;
|
||||
if (base == ULL(0xfffffc0000000000))
|
||||
return 0;
|
||||
|
@ -88,14 +84,13 @@ namespace AlphaISA
|
|||
|
||||
vp = tc->getVirtPort();
|
||||
tsk = vp->readGtoH<Addr>(base + task_off);
|
||||
tc->delVirtPort(vp);
|
||||
|
||||
return tsk;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ProcessInfo::pid(Addr ksp) const
|
||||
{
|
||||
int
|
||||
ProcessInfo::pid(Addr ksp) const
|
||||
{
|
||||
Addr task = this->task(ksp);
|
||||
if (!task)
|
||||
return -1;
|
||||
|
@ -106,14 +101,13 @@ namespace AlphaISA
|
|||
|
||||
vp = tc->getVirtPort();
|
||||
pd = vp->readGtoH<uint16_t>(task + pid_off);
|
||||
tc->delVirtPort(vp);
|
||||
|
||||
return pd;
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
ProcessInfo::name(Addr ksp) const
|
||||
{
|
||||
string
|
||||
ProcessInfo::name(Addr ksp) const
|
||||
{
|
||||
Addr task = this->task(ksp);
|
||||
if (!task)
|
||||
return "console";
|
||||
|
@ -124,33 +118,35 @@ namespace AlphaISA
|
|||
return "startup";
|
||||
|
||||
return comm;
|
||||
}
|
||||
}
|
||||
|
||||
StackTrace::StackTrace()
|
||||
StackTrace::StackTrace()
|
||||
: tc(0), stack(64)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
|
||||
StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
|
||||
: tc(0), stack(64)
|
||||
{
|
||||
{
|
||||
trace(_tc, inst);
|
||||
}
|
||||
}
|
||||
|
||||
StackTrace::~StackTrace()
|
||||
{
|
||||
}
|
||||
StackTrace::~StackTrace()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
||||
{
|
||||
void
|
||||
StackTrace::trace(ThreadContext *_tc, bool is_call)
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -214,35 +209,35 @@ namespace AlphaISA
|
|||
}
|
||||
|
||||
panic("unwinding too far");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
StackTrace::isEntry(Addr addr)
|
||||
{
|
||||
if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp12))
|
||||
bool
|
||||
StackTrace::isEntry(Addr addr)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
StackTrace::decodeStack(MachInst inst, int &disp)
|
||||
{
|
||||
bool
|
||||
StackTrace::decodeStack(MachInst inst, int &disp)
|
||||
{
|
||||
// lda $sp, -disp($sp)
|
||||
//
|
||||
// Opcode<31:26> == 0x08
|
||||
|
@ -279,11 +274,11 @@ namespace AlphaISA
|
|||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
StackTrace::decodeSave(MachInst inst, int ®, int &disp)
|
||||
{
|
||||
bool
|
||||
StackTrace::decodeSave(MachInst inst, int ®, int &disp)
|
||||
{
|
||||
// lda $stq, disp($sp)
|
||||
//
|
||||
// Opcode<31:26> == 0x08
|
||||
|
@ -304,16 +299,16 @@ namespace AlphaISA
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Decode the function prologue for the function we're in, and note
|
||||
* 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)
|
||||
{
|
||||
bool
|
||||
StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, int &size,
|
||||
Addr &ra)
|
||||
{
|
||||
size = 0;
|
||||
ra = 0;
|
||||
|
||||
|
@ -340,12 +335,12 @@ namespace AlphaISA
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#if TRACING_ON
|
||||
void
|
||||
StackTrace::dump()
|
||||
{
|
||||
void
|
||||
StackTrace::dump()
|
||||
{
|
||||
StringWrap name(tc->getCpuPtr()->name());
|
||||
SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
|
||||
|
||||
|
@ -365,6 +360,7 @@ namespace AlphaISA
|
|||
|
||||
DPRINTFN("%#x: %s\n", addr, symbol);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
|
||||
class ThreadContext;
|
||||
|
||||
namespace AlphaISA
|
||||
{
|
||||
class StackTrace;
|
||||
namespace AlphaISA {
|
||||
|
||||
class ProcessInfo
|
||||
{
|
||||
class StackTrace;
|
||||
|
||||
class ProcessInfo
|
||||
{
|
||||
private:
|
||||
ThreadContext *tc;
|
||||
|
||||
|
@ -57,12 +57,10 @@ namespace AlphaISA
|
|||
Addr task(Addr ksp) const;
|
||||
int pid(Addr ksp) const;
|
||||
std::string name(Addr ksp) const;
|
||||
};
|
||||
};
|
||||
|
||||
class StackTrace
|
||||
{
|
||||
protected:
|
||||
typedef TheISA::MachInst MachInst;
|
||||
class StackTrace
|
||||
{
|
||||
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();
|
||||
|
@ -106,11 +105,11 @@ namespace AlphaISA
|
|||
public:
|
||||
void dprintf() {}
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
inline bool
|
||||
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
||||
{
|
||||
inline bool
|
||||
StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
|
||||
{
|
||||
if (!inst->isCall() && !inst->isReturn())
|
||||
return false;
|
||||
|
||||
|
@ -119,7 +118,8 @@ namespace AlphaISA
|
|||
|
||||
trace(tc, !inst->isReturn());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ARCH_ALPHA_STACKTRACE_HH__
|
||||
|
|
|
@ -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,15 +182,15 @@ 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
|
||||
|
@ -203,7 +201,6 @@ AlphaSystem::serialize(std::ostream &os)
|
|||
palSymtab->serialize("pal_symtab", os);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
|
|
|
@ -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 §ion);
|
||||
|
||||
|
@ -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__
|
||||
|
||||
|
|
|
@ -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
|
||||
// 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 §ion)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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);
|
||||
if (FULL_SYSTEM && PcPAL(req->getPC()))
|
||||
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,15 +397,23 @@ 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
|
||||
//
|
||||
DTB::DTB(const Params *p)
|
||||
DTB::DTB(const Params *p)
|
||||
: TLB(p)
|
||||
{}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,12 +48,12 @@
|
|||
|
||||
class ThreadContext;
|
||||
|
||||
namespace AlphaISA
|
||||
{
|
||||
class TlbEntry;
|
||||
namespace AlphaISA {
|
||||
|
||||
class TLB : public BaseTLB
|
||||
{
|
||||
class TlbEntry;
|
||||
|
||||
class TLB : public BaseTLB
|
||||
{
|
||||
protected:
|
||||
typedef std::multimap<Addr, int> PageTable;
|
||||
PageTable lookupTable; // Quick lookup into page table
|
||||
|
@ -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,25 +103,27 @@ 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;
|
||||
return entry;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ITB : public TLB
|
||||
{
|
||||
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
|
||||
{
|
||||
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__
|
||||
|
|
|
@ -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,8 +569,7 @@ AlphaTru64Process::getDesc(int callnum)
|
|||
return &syscallDescs[callnum];
|
||||
}
|
||||
|
||||
|
||||
AlphaTru64Process::AlphaTru64Process(LiveProcessParams * params,
|
||||
AlphaTru64Process::AlphaTru64Process(LiveProcessParams *params,
|
||||
ObjectFile *objFile)
|
||||
: AlphaLiveProcess(params, objFile),
|
||||
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)),
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -51,9 +52,9 @@ class AlphaTru64Process : public AlphaLiveProcess
|
|||
const int Num_Syscall_Descs;
|
||||
const int Num_Mach_Syscall_Descs;
|
||||
|
||||
virtual SyscallDesc* getDesc(int callnum);
|
||||
virtual SyscallDesc *getDesc(int callnum);
|
||||
};
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif // __ALPHA_TRU64_PROCESS_HH__
|
||||
#endif // __ARCH_ALPHA_TRU64_PROCESS_HH__
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -32,47 +32,43 @@
|
|||
#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;
|
||||
typedef uint8_t RegIndex;
|
||||
|
||||
typedef uint64_t IntReg;
|
||||
typedef uint64_t LargestRead;
|
||||
|
||||
// floating point register file entry type
|
||||
typedef double FloatReg;
|
||||
typedef uint64_t FloatRegBits;
|
||||
|
||||
// control register file contents
|
||||
typedef uint64_t MiscReg;
|
||||
|
||||
union AnyReg
|
||||
{
|
||||
|
||||
typedef uint32_t MachInst;
|
||||
typedef uint64_t ExtMachInst;
|
||||
typedef uint8_t RegIndex;
|
||||
|
||||
typedef uint64_t IntReg;
|
||||
typedef uint64_t LargestRead;
|
||||
|
||||
// floating point register file entry type
|
||||
typedef double FloatReg;
|
||||
typedef uint64_t FloatRegBits;
|
||||
|
||||
// control register file contents
|
||||
typedef uint64_t MiscReg;
|
||||
|
||||
typedef union {
|
||||
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__
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -32,127 +32,137 @@
|
|||
#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);
|
||||
|
||||
inline bool
|
||||
inUserMode(ThreadContext *tc)
|
||||
{
|
||||
return (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
|
||||
}
|
||||
|
||||
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
|
||||
|
||||
static inline bool
|
||||
inUserMode(ThreadContext *tc)
|
||||
{
|
||||
return (tc->readMiscRegNoEffect(AlphaISA::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) {
|
||||
// Instruction address compression hooks
|
||||
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() {
|
||||
// the size of "fetched" instructions (not necessarily the size
|
||||
// of real instructions for PISA)
|
||||
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
|
||||
// Machine operations
|
||||
void saveMachineReg(AnyReg &savereg, const RegFile ®_file, int regnum);
|
||||
void restoreMachineReg(RegFile ®s, const AnyReg ®, int regnum);
|
||||
|
||||
void saveMachineReg(AnyReg &savereg, const RegFile ®_file,
|
||||
int regnum);
|
||||
|
||||
void restoreMachineReg(RegFile ®s, const AnyReg ®,
|
||||
int regnum);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Function to insure ISA semantics about 0 registers.
|
||||
* @param tc The thread context.
|
||||
*/
|
||||
template <class TC>
|
||||
void zeroRegisters(TC *tc);
|
||||
template <class TC>
|
||||
void zeroRegisters(TC *tc);
|
||||
|
||||
// Alpha IPR register accessors
|
||||
inline bool PcPAL(Addr addr) { return addr & 0x3; }
|
||||
inline void startupCPU(ThreadContext *tc, int cpuId) {
|
||||
tc->activate(0);
|
||||
}
|
||||
// Alpha IPR register accessors
|
||||
inline bool PcPAL(Addr addr) { return addr & 0x3; }
|
||||
inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Translation stuff
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Translation stuff
|
||||
//
|
||||
|
||||
inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; }
|
||||
inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; }
|
||||
|
||||
// User Virtual
|
||||
inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; }
|
||||
// User Virtual
|
||||
inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; }
|
||||
|
||||
// Kernel Direct Mapped
|
||||
inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; }
|
||||
inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; }
|
||||
// Kernel Direct Mapped
|
||||
inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; }
|
||||
inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; }
|
||||
|
||||
// Kernel Virtual
|
||||
inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; }
|
||||
// Kernel Virtual
|
||||
inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; }
|
||||
|
||||
inline Addr
|
||||
TruncPage(Addr addr)
|
||||
{ return addr & ~(PageBytes - 1); }
|
||||
inline Addr
|
||||
TruncPage(Addr addr)
|
||||
{ return addr & ~(PageBytes - 1); }
|
||||
|
||||
inline Addr
|
||||
RoundPage(Addr addr)
|
||||
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
|
||||
inline Addr
|
||||
RoundPage(Addr addr)
|
||||
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
|
||||
|
||||
void initIPRs(ThreadContext *tc, int cpuId);
|
||||
void initIPRs(ThreadContext *tc, int cpuId);
|
||||
#if FULL_SYSTEM
|
||||
void initCPU(ThreadContext *tc, int cpuId);
|
||||
void initCPU(ThreadContext *tc, int cpuId);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Function to check for and process any interrupts.
|
||||
* @param tc The thread context.
|
||||
*/
|
||||
template <class TC>
|
||||
void processInterrupts(TC *tc);
|
||||
template <class TC>
|
||||
void processInterrupts(TC *tc);
|
||||
#endif
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
#endif
|
||||
#endif // __ARCH_ALPHA_UTILITY_HH__
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
Addr vtophys(Addr vaddr);
|
||||
Addr vtophys(ThreadContext *tc, Addr vaddr);
|
||||
|
||||
} // namespace AlphaISA
|
||||
|
||||
};
|
||||
#endif // __ARCH_ALPHA_VTOPHYS_H__
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue