Merge m5.eecs.umich.edu:/bk/newmem

into  ewok.(none):/home/gblack/m5/newmem

--HG--
extra : convert_revision : 516c357f98c7a571c70362babd3fa162fbc2ed5a
This commit is contained in:
Gabe Black
2006-07-18 18:23:23 -04:00
290 changed files with 22098 additions and 5816 deletions

42
AUTHORS Normal file
View File

@@ -0,0 +1,42 @@
Steven K. Reinhardt
-----------------------
Nathan L. Binkert
-----------------------
Erik G. Hallnor
-----------------------
Steve E. Raasch
-----------------------
Lisa R. Hsu
-----------------------
Ali G. Saidi
-----------------------
Andrew L. Schultz
-----------------------
Kevin T. Lim
-----------------------
Ronald G. Dreslinski Jr
-----------------------
Gabriel Black
-----------------------
Korey L. Sewell
-----------------------
David Green
-----------------------
Benjamin S. Nash
-----------------------
Miguel J. Serrano
-----------------------

88
README
View File

@@ -1,21 +1,27 @@
This is release m5_1.1 of the M5 simulator.
This is release 2.0 of the M5 simulator.
This file contains brief "getting started" instructions. For more
information, see http://m5.eecs.umich.edu. If you have questions,
please send mail to m5sim-users@lists.sourceforge.net.
For information about building the simulator and getting started please refer
to: http://m5.eecs.umich.edu/
Specific Pages of Interest are:
http://m5.eecs.umich.edu/wiki/index.php/Compiling_M5
http://m5.eecs.umich.edu/wiki/index.php/Running_M5
If you have questions, please send mail to m5sim-users@lists.sourceforge.net.
WHAT'S INCLUDED (AND NOT)
-------------------------
The basic source release includes these subdirectories:
- m5: the simulator itself
- m5-test: regression tests
- ext: less-common external packages needed to build m5
- alpha-system: source for Alpha console and PALcode
- m5:
- src: source code of the m5 simulator
- test: regression tests
- ext: less-common external packages needed to build m5
- system/alpha: source for Alpha console and PALcode
To run full-system simulations, you will need compiled console,
PALcode, and kernel binaries and one or more disk images. These files
are collected in a separate archive, m5_system_1.1.tar.bz2. This file
are collected in a separate archive, m5_system_2.0.tar.bz2. This file
is included on the CD release, or you can download it separately from
Sourceforge.
@@ -31,66 +37,8 @@ set of Linux source patches (linux_m5-2.6.8.1.diff), and the scons
program needed to build M5. If you do not have the CD, the same HTML
documentation is available online at http://m5.eecs.umich.edu/docs,
the Linux source patches are available at
http://m5.eecs.umich.edu/dist/linux_m5-2.6.8.1.diff, and the scons
program is available from http://www.scons.org.
http://m5.eecs.umich.edu/dist/linux_m5-2.6.8.1.diff, the scons
program is available from http://www.scons.org, and swig is available from
http://www.swig.org.
WHAT'S NEEDED
-------------
- GCC version 3.3 or newer
- Python 2.3 or newer
- SCons 0.96.1 or newer (see http://www.scons.org)
WHAT'S RECOMMENDED
------------------
- MySQL (for statistics complex statistics storage/retrieval)
- Python-MysqlDB (for statistics analysis)
GETTING STARTED
---------------
There are two different build targets and three optimizations levels:
Target:
-------
ALPHA_SE - Syscall emulation simulation
ALPHA_FS - Full system simulation
Optimization:
-------------
m5.debug - debug version of the code with tracing and without optimization
m5.opt - optimized version of code with tracing
m5.fast - optimized version of the code without tracing and asserts
Different targets are built in different subdirectories of m5/build.
Binaries with the same target but different optimization levels share
the same directory. Note that you can build m5 in any directory you
choose;p just configure the target directory using the 'mkbuilddir'
script in m5/build.
The following steps will build and test the simulator. The variable
"$top" refers to the top directory where you've unpacked the files,
i.e., the one containing the m5, m5-test, and ext directories. If you
have a multiprocessor system, you should give scons a "-j N" argument (like
make) to run N jobs in parallel.
To build and test the syscall-emulation simulator:
cd $top/m5/build
scons ALPHA_SE/test/opt/quick
This process takes under 10 minutes on a dual 3GHz Xeon system (using
the '-j 4' option).
To build and test the full-system simulator:
1. Unpack the full-system binaries from m5_system_1.1.tar.bz2. (See
above for directions on obtaining this file if you don't have it.)
This package includes disk images and kernel, palcode, and console
binaries for Linux and FreeBSD.
2. Edit the SYSTEMDIR search path in $top/m5-test/SysPaths.py to
include the path to your local copy of the binaries.
3. In $top/m5/build, run "scons ALPHA_FS/test/opt/quick".
This process also takes under 10 minutes on a dual 3GHz Xeon system
(again using the '-j 4' option).

View File

@@ -1,3 +1,11 @@
XXX. X, 2006: m5_2.0
--------------------
Major update to M5 including:
- New CPU model
- Sew memory system
- More extensive python integration
- Preliminary syscall emulation support for MIPS and SPARC
Oct. 8, 2005: m5_1.1
--------------------
Update release for IOSCA workshop mini-tutorial. New features include:

View File

@@ -39,17 +39,20 @@
#
# You can build M5 in a different directory as long as there is a
# 'build/<CONFIG>' somewhere along the target path. The build system
# expdects that all configs under the same build directory are being
# expects that all configs under the same build directory are being
# built for the same host system.
#
# Examples:
# These two commands are equivalent. The '-u' option tells scons to
# search up the directory tree for this SConstruct file.
#
# The following two commands are equivalent. The '-u' option tells
# scons to search up the directory tree for this SConstruct file.
# % cd <path-to-src>/m5 ; scons build/ALPHA_FS/m5.debug
# % cd <path-to-src>/m5/build/ALPHA_FS; scons -u m5.debug
# These two commands are equivalent and demonstrate building in a
# directory outside of the source tree. The '-C' option tells scons
# to chdir to the specified directory to find this SConstruct file.
#
# The following two commands are equivalent and demonstrate building
# in a directory outside of the source tree. The '-C' option tells
# scons to chdir to the specified directory to find this SConstruct
# file.
# % cd <path-to-src>/m5 ; scons /local/foo/build/ALPHA_FS/m5.debug
# % cd /local/foo/build/ALPHA_FS; scons -C <path-to-src>/m5 m5.debug
#
@@ -156,7 +159,7 @@ env = Environment(ENV = os.environ, # inherit user's environment vars
ROOT = ROOT,
SRCDIR = SRCDIR)
env.SConsignFile("sconsign")
env.SConsignFile(os.path.join(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
@@ -260,8 +263,8 @@ env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips']
# Define the universe of supported CPU models
env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
'FullCPU', 'AlphaFullCPU',
'OzoneSimpleCPU', 'OzoneCPU', 'CheckerCPU']
'FullCPU', 'O3CPU',
'OzoneCPU']
# Sticky options get saved in the options file so they persist from
# one invocation to the next (unless overridden, in which case the new
@@ -289,6 +292,7 @@ sticky_opts.AddOptions(
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),
('CC', 'C compiler', os.environ.get('CC', env['CC'])),
('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])),
BoolOption('BATCH', 'Use batch pool for build and tests', False),
@@ -301,9 +305,10 @@ nonsticky_opts.AddOptions(
BoolOption('update_ref', 'Update test reference outputs', False)
)
# These options get exported to #defines in config/*.hh (see m5/SConscript).
# 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_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
'USE_CHECKER']
# Define a handy 'no-op' action
def no_action(target, source, env):
@@ -482,7 +487,7 @@ for build_path in build_paths:
if env['USE_SSE2']:
env.Append(CCFLAGS='-msse2')
# The m5/SConscript file sets up the build rules in 'env' according
# The src/SConscript file sets up the build rules in 'env' according
# to the configured options. It returns a list of environments,
# one for each variant build (debug, opt, etc.)
envList = SConscript('src/SConscript', build_dir = build_path,

View File

@@ -1,32 +1,40 @@
from m5 import *
import os.path
import sys
# Edit the following list to include the possible paths to the binary
# and disk image directories. The first directory on the list that
# exists will be selected.
SYSTEMDIR_PATH = ['/n/poolfs/z/dist/m5/system']
SYSTEMDIR = None
for d in SYSTEMDIR_PATH:
if os.path.exists(d):
SYSTEMDIR = d
break
if not SYSTEMDIR:
print >>sys.stderr, "Can't find a path to system files."
sys.exit(1)
BINDIR = SYSTEMDIR + '/binaries'
DISKDIR = SYSTEMDIR + '/disks'
import os, sys
from os.path import isdir, join as joinpath
from os import environ as env
def disk(file):
return os.path.join(DISKDIR, file)
system()
return joinpath(disk.dir, file)
def binary(file):
return os.path.join(BINDIR, file)
system()
return joinpath(binary.dir, file)
def script(file):
return os.path.join(SYSTEMDIR, 'boot', file)
system()
return joinpath(script.dir, file)
def system():
if not system.dir:
try:
path = env['M5_PATH'].split(':')
except KeyError:
path = [ '/dist/m5/system', '/n/poolfs/z/dist/m5/system' ]
for system.dir in path:
if os.path.isdir(system.dir):
break
else:
raise ImportError, "Can't find a path to system files."
if not binary.dir:
binary.dir = joinpath(system.dir, 'binaries')
if not disk.dir:
disk.dir = joinpath(system.dir, 'disks')
if not script.dir:
script.dir = joinpath(system.dir, 'boot')
system.dir = None
binary.dir = None
disk.dir = None
script.dir = None

View File

@@ -1,9 +1,10 @@
import optparse, os, sys
import m5
from m5.objects import *
import os
from SysPaths import *
parser = optparse.OptionParser(option_list=m5.standardOptions)
parser = optparse.OptionParser()
parser.add_option("-t", "--timing", action="store_true")
@@ -16,6 +17,8 @@ if args:
# Base for tests is directory containing this file.
test_base = os.path.dirname(__file__)
script.dir = '/z/saidi/work/m5.newmem/configs/boot'
linux_image = env.get('LINUX_IMAGE', disk('linux-latest.img'))
class IdeControllerPciData(PciConfigData):
@@ -97,7 +100,7 @@ class SpecwebFilesetDisk(IdeDisk):
class BaseTsunami(Tsunami):
cchip = TsunamiCChip(pio_addr=0x801a0000000)
pchip = TsunamiPChip(pio_addr=0x80180000000)
pciconfig = PciConfigAll(pio_addr=0x801fe000000)
pciconfig = PciConfigAll()
fake_sm_chip = IsaFake(pio_addr=0x801fc000370)
fake_uart1 = IsaFake(pio_addr=0x801fc0002f8)
@@ -129,17 +132,7 @@ class BaseTsunami(Tsunami):
ethernet = NSGigE(configdata=NSGigEPciData(),
pci_bus=0, pci_dev=1, pci_func=0)
etherint = NSGigEInt(device=Parent.ethernet)
# ethernet = Sinic(configdata=SinicPciData(),
# pci_bus=0, pci_dev=1, pci_func=0)
# etherint = SinicInt(device=Parent.ethernet)
console = AlphaConsole(pio_addr=0x80200000000, disk=Parent.simple_disk)
# bridge = PciFake(configdata=BridgePciData(), pci_bus=0, pci_dev=2, pci_func=0)
#class FreeBSDTsunami(BaseTsunami):
# disk0 = FreeBSDRootDisk(delay='0us', driveID='master')
# ide = IdeController(disks=[Parent.disk0],
# configdata=IdeControllerPciData(),
# pci_func=0, pci_dev=0, pci_bus=0)
class LinuxTsunami(BaseTsunami):
disk0 = LinuxRootDisk(driveID='master')
@@ -149,56 +142,62 @@ class LinuxTsunami(BaseTsunami):
configdata=IdeControllerPciData(),
pci_func=0, pci_dev=0, pci_bus=0)
class LinuxAlphaSystem(LinuxAlphaSystem):
class MyLinuxAlphaSystem(LinuxAlphaSystem):
magicbus = Bus(bus_id=0)
magicbus2 = Bus(bus_id=1)
bridge = Bridge()
physmem = PhysicalMemory(range = AddrRange('128MB'))
c0a = Connector(side_a=Parent.magicbus, side_b=Parent.bridge, side_b_name="side_a")
c0b = Connector(side_a=Parent.magicbus2, side_b=Parent.bridge, side_b_name="side_b")
c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2)
bridge.side_a = magicbus.port
bridge.side_b = magicbus2.port
physmem.port = magicbus2.port
tsunami = LinuxTsunami()
c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus)
c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus)
c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus)
c5 = Connector(side_a=Parent.tsunami.fake_sm_chip, side_a_name='pio', side_b=Parent.magicbus)
c6 = Connector(side_a=Parent.tsunami.ethernet, side_a_name='pio', side_b=Parent.magicbus)
c6a = Connector(side_a=Parent.tsunami.ethernet, side_a_name='dma', side_b=Parent.magicbus)
c7 = Connector(side_a=Parent.tsunami.fake_uart1, side_a_name='pio', side_b=Parent.magicbus)
c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus)
c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus)
c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus)
c11 = Connector(side_a=Parent.tsunami.ide, side_a_name='pio', side_b=Parent.magicbus)
c13 = Connector(side_a=Parent.tsunami.ide, side_a_name='dma', side_b=Parent.magicbus)
c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus)
c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus)
c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus)
c17 = Connector(side_a=Parent.tsunami.fake_pnp_write, side_a_name='pio', side_b=Parent.magicbus)
c18 = Connector(side_a=Parent.tsunami.fake_pnp_read0, side_a_name='pio', side_b=Parent.magicbus)
c19 = Connector(side_a=Parent.tsunami.fake_pnp_read1, side_a_name='pio', side_b=Parent.magicbus)
c20 = Connector(side_a=Parent.tsunami.fake_pnp_read2, side_a_name='pio', side_b=Parent.magicbus)
c21 = Connector(side_a=Parent.tsunami.fake_pnp_read3, side_a_name='pio', side_b=Parent.magicbus)
c22 = Connector(side_a=Parent.tsunami.fake_pnp_read4, side_a_name='pio', side_b=Parent.magicbus)
c23 = Connector(side_a=Parent.tsunami.fake_pnp_read5, side_a_name='pio', side_b=Parent.magicbus)
c24 = Connector(side_a=Parent.tsunami.fake_pnp_read6, side_a_name='pio', side_b=Parent.magicbus)
c25 = Connector(side_a=Parent.tsunami.fake_pnp_read7, side_a_name='pio', side_b=Parent.magicbus)
c27 = Connector(side_a=Parent.tsunami.fake_ata0, side_a_name='pio', side_b=Parent.magicbus)
c28 = Connector(side_a=Parent.tsunami.fake_ata1, side_a_name='pio', side_b=Parent.magicbus)
c30 = Connector(side_a=Parent.tsunami.fb, side_a_name='pio', side_b=Parent.magicbus)
c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus)
c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus)
c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus)
tsunami.cchip.pio = magicbus.port
tsunami.pchip.pio = magicbus.port
tsunami.pciconfig.pio = magicbus.default
tsunami.fake_sm_chip.pio = magicbus.port
tsunami.ethernet.pio = magicbus.port
tsunami.ethernet.dma = magicbus.port
tsunami.ethernet.config = magicbus.port
tsunami.fake_uart1.pio = magicbus.port
tsunami.fake_uart2.pio = magicbus.port
tsunami.fake_uart3.pio = magicbus.port
tsunami.fake_uart4.pio = magicbus.port
tsunami.ide.pio = magicbus.port
tsunami.ide.dma = magicbus.port
tsunami.ide.config = magicbus.port
tsunami.fake_ppc.pio = magicbus.port
tsunami.fake_OROM.pio = magicbus.port
tsunami.fake_pnp_addr.pio = magicbus.port
tsunami.fake_pnp_write.pio = magicbus.port
tsunami.fake_pnp_read0.pio = magicbus.port
tsunami.fake_pnp_read1.pio = magicbus.port
tsunami.fake_pnp_read2.pio = magicbus.port
tsunami.fake_pnp_read3.pio = magicbus.port
tsunami.fake_pnp_read4.pio = magicbus.port
tsunami.fake_pnp_read5.pio = magicbus.port
tsunami.fake_pnp_read6.pio = magicbus.port
tsunami.fake_pnp_read7.pio = magicbus.port
tsunami.fake_ata0.pio = magicbus.port
tsunami.fake_ata1.pio = magicbus.port
tsunami.fb.pio = magicbus.port
tsunami.io.pio = magicbus.port
tsunami.uart.pio = magicbus.port
tsunami.console.pio = magicbus.port
raw_image = RawDiskImage(image_file=disk('linux-latest.img'),
read_only=True)
simple_disk = SimpleDisk(disk=Parent.raw_image)
intrctrl = IntrControl()
if options.timing:
cpu = TimingSimpleCPU()
mem_mode = 'timing'
else:
cpu = AtomicSimpleCPU()
cpu.mem = Parent.magicbus2
cpu.mem = magicbus2
cpu.icache_port = magicbus2.port
cpu.dcache_port = magicbus2.port
cpu.itb = AlphaITB()
cpu.dtb = AlphaDTB()
cpu.clock = '2GHz'
sim_console = SimConsole(listener=ConsoleListener(port=3456))
kernel = binary('vmlinux')
pal = binary('ts_osfpal')
@@ -221,14 +220,23 @@ def DualRoot(clientSystem, serverSystem):
self.etherlink = EtherLink(int1 = Parent.client.tsunami.etherint[0],
int2 = Parent.server.tsunami.etherint[0],
dump = Parent.etherdump)
self.clock = '5GHz'
self.clock = '1THz'
return self
root = DualRoot(LinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')),
LinuxAlphaSystem(readfile=script('netperf-server.rcS')))
root = DualRoot(
MyLinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')),
MyLinuxAlphaSystem(readfile=script('netperf-server.rcS')))
m5.instantiate(root)
#exit_event = m5.simulate(2600000000000)
#if exit_event.getCause() != "user interrupt received":
# m5.checkpoint(root, 'cpt')
# exit_event = m5.simulate(300000000000)
# if exit_event.getCause() != "user interrupt received":
# m5.checkpoint(root, 'cptA')
exit_event = m5.simulate()
print 'Exiting @', m5.curTick(), 'because', exit_event.getCause()
print 'Exiting @ cycle', m5.curTick(), 'because', exit_event.getCause()

View File

@@ -4,14 +4,27 @@
# MIPS: "m5 test.py -a Mips -c hello_mips"
import os, optparse, sys
import m5
from m5.objects import *
from FullO3Config import *
# parse command-line arguments
parser = optparse.OptionParser(option_list=m5.standardOptions)
parser = optparse.OptionParser()
parser.add_option("-c", "--cmd", default="hello")
parser.add_option("-t", "--timing", action="store_true")
parser.add_option("-c", "--cmd", default="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.")
parser.add_option("-t", "--timing", action="store_true",
help="Use simple timing CPU.")
parser.add_option("-d", "--detailed", action="store_true",
help="Use detailed CPU.")
parser.add_option("-m", "--maxtick", type="int",
help="Set the maximum number of ticks to run for")
(options, args) = parser.parse_args()
@@ -24,27 +37,64 @@ this_dir = os.path.dirname(__file__)
process = LiveProcess()
process.executable = os.path.join(this_dir, options.cmd)
process.cmd = options.cmd
process.cmd = options.cmd + " " + options.options
if options.input != "":
process.input = options.input
magicbus = Bus()
mem = PhysicalMemory()
if options.timing and options.detailed:
print "Error: you may only specify one cpu model";
sys.exit(1)
if options.timing:
cpu = TimingSimpleCPU()
elif options.detailed:
#check for SMT workload
workloads = options.cmd.split(';')
if len(workloads) > 1:
process = []
smt_idx = 0
inputs = []
if options.input != "":
inputs = options.input.split(';')
for wrkld in workloads:
smt_process = LiveProcess()
smt_process.executable = os.path.join(this_dir, wrkld)
smt_process.cmd = wrkld + " " + options.options
if inputs and inputs[smt_idx]:
smt_process.input = inputs[smt_idx]
process += [smt_process, ]
smt_idx += 1
cpu = DetailedO3CPU()
else:
cpu = AtomicSimpleCPU()
cpu.workload = process
cpu.mem = magicbus
cpu.icache_port=magicbus.port
cpu.dcache_port=magicbus.port
system = System(physmem = mem, cpu = cpu)
system.c1 = Connector(side_a = mem, side_b = magicbus)
if options.timing or options.detailed:
system.mem_mode = 'timing'
mem.port = magicbus.port
root = Root(system = system)
# instantiate configuration
m5.instantiate(root)
# simulate until program terminates
exit_event = m5.simulate()
if options.maxtick:
exit_event = m5.simulate(options.maxtick)
else:
exit_event = m5.simulate()
print 'Exiting @', m5.curTick(), 'because', exit_event.getCause()
print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()

View File

@@ -62,7 +62,6 @@ base_sources = Split('''
base/range.cc
base/random.cc
base/sat_counter.cc
base/serializer.cc
base/socket.cc
base/statistics.cc
base/str.cc
@@ -85,33 +84,54 @@ base_sources = Split('''
cpu/base.cc
cpu/cpuevent.cc
cpu/exetrace.cc
cpu/func_unit.cc
cpu/op_class.cc
cpu/pc_event.cc
cpu/quiesce_event.cc
cpu/static_inst.cc
cpu/sampler/sampler.cc
cpu/simple_thread.cc
cpu/thread_state.cc
encumbered/cpu/full/fu_pool.cc
mem/bridge.cc
mem/bus.cc
mem/connector.cc
mem/mem_object.cc
mem/packet.cc
mem/physical.cc
mem/port.cc
mem/cache/base_cache.cc
mem/cache/cache.cc
mem/cache/coherence/coherence_protocol.cc
mem/cache/coherence/uni_coherence.cc
mem/cache/miss/blocking_buffer.cc
mem/cache/miss/miss_queue.cc
mem/cache/miss/mshr.cc
mem/cache/miss/mshr_queue.cc
mem/cache/prefetch/base_prefetcher.cc
mem/cache/prefetch/ghb_prefetcher.cc
mem/cache/prefetch/prefetcher.cc
mem/cache/prefetch/stride_prefetcher.cc
mem/cache/prefetch/tagged_prefetcher.cc
mem/cache/tags/base_tags.cc
mem/cache/tags/cache_tags.cc
mem/cache/tags/fa_lru.cc
mem/cache/tags/iic.cc
mem/cache/tags/lru.cc
mem/cache/tags/repl/gen.cc
mem/cache/tags/repl/repl.cc
mem/cache/tags/split.cc
mem/cache/tags/split_lifo.cc
mem/cache/tags/split_lru.cc
mem/cache/cache_builder.cc
sim/builder.cc
sim/configfile.cc
sim/debug.cc
sim/eventq.cc
sim/faults.cc
sim/main.cc
python/swig/main_wrap.cc
python/swig/cc_main_wrap.cc
sim/param.cc
sim/profile.cc
sim/root.cc
sim/serialize.cc
sim/sim_events.cc

View File

@@ -28,7 +28,7 @@
#
# Authors: Steve Reinhardt
import os.path
import os.path, sys
# Import build environment variable from SConstruct.
Import('env')
@@ -128,13 +128,19 @@ isa_desc_gen_files = Split('decoder.cc decoder.hh')
isa_desc_gen_files += [CpuModel.dict[cpu].filename
for cpu in env['CPU_MODELS']]
# Also include the CheckerCPU as one of the models if it is being
# enabled via command line.
if env['USE_CHECKER']:
isa_desc_gen_files += [CpuModel.dict['CheckerCPU'].filename]
# The emitter patches up the sources & targets to include the
# autogenerated files as targets and isa parser itself as a source.
def isa_desc_emitter(target, source, env):
return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
# Pieces are in place, so create the builder.
isa_desc_builder = Builder(action='python2.4 $SOURCES $TARGET.dir $CPU_MODELS',
python = sys.executable # use same Python binary used to run scons
isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS',
emitter = isa_desc_emitter)
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })

View File

@@ -59,8 +59,12 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId)
tc->setIntReg(16, cpuId);
tc->setIntReg(0, cpuId);
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect());
AlphaFault *reset = new ResetFault;
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + reset->vect());
tc->setNextPC(tc->readPC() + sizeof(MachInst));
delete reset;
}
////////////////////////////////////////////////////////////////////////

View File

@@ -35,6 +35,9 @@
#include "base/trace.hh"
#if FULL_SYSTEM
#include "arch/alpha/ev5.hh"
#else
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace AlphaISA
@@ -56,6 +59,12 @@ FaultName ArithmeticFault::_name = "arith";
FaultVect ArithmeticFault::_vect = 0x0501;
FaultStat ArithmeticFault::_count;
#if !FULL_SYSTEM
FaultName PageTableFault::_name = "page_table_fault";
FaultVect PageTableFault::_vect = 0x0000;
FaultStat PageTableFault::_count;
#endif
FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0101;
FaultStat InterruptFault::_count;
@@ -173,6 +182,30 @@ void ItbFault::invoke(ThreadContext * tc)
AlphaFault::invoke(tc);
}
#else //!FULL_SYSTEM
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
// address is higher than the stack region or in the current stack region
if (vaddr > p->stack_base || vaddr > p->stack_min)
FaultBase::invoke(tc);
// We've accessed the next page
if (vaddr > p->stack_min - PageBytes) {
warn("Increasing stack %#x:%#x to %#x:%#x because of access to %#x",
p->stack_min, p->stack_base, p->stack_min - PageBytes,
p->stack_base, vaddr);
p->stack_min -= PageBytes;
if (p->stack_base - p->stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
p->pTable->allocate(p->stack_min, PageBytes);
} else {
FaultBase::invoke(tc);
}
}
#endif
} // namespace AlphaISA

View File

@@ -81,6 +81,29 @@ class AlignmentFault : public AlphaFault
bool isAlignmentFault() {return true;}
};
#if !FULL_SYSTEM
class PageTableFault : public AlphaFault
{
private:
Addr vaddr;
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
PageTableFault(Addr va)
: vaddr(va) {}
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
static inline Fault genPageTableFault(Addr va)
{
return new PageTableFault(va);
}
#endif
static inline Fault genMachineCheckFault()
{
return new MachineCheckFault;

View File

@@ -97,6 +97,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -115,6 +116,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -133,6 +136,7 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -47,9 +47,11 @@ decode OPCODE default Unknown::unknown() {
0x23: ldt({{ Fa = Mem.df; }});
0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
#ifdef USE_COPY
0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
{{ fault = xc->copySrcTranslate(EA); }},
inst_flags = [IsMemRef, IsLoad, IsCopy]);
#endif
}
format LoadOrPrefetch {
@@ -69,9 +71,11 @@ decode OPCODE default Unknown::unknown() {
0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ Mem.df = Fa; }});
#ifdef USE_COPY
0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
{{ fault = xc->copy(EA); }},
inst_flags = [IsMemRef, IsStore, IsCopy]);
#endif
}
format StoreCond {
@@ -659,11 +663,11 @@ decode OPCODE default Unknown::unknown() {
0xe000: rc({{
Ra = xc->readIntrFlag();
xc->setIntrFlag(0);
}}, IsNonSpeculative);
}}, IsNonSpeculative, IsUnverifiable);
0xf000: rs({{
Ra = xc->readIntrFlag();
xc->setIntrFlag(1);
}}, IsNonSpeculative);
}}, IsNonSpeculative, IsUnverifiable);
}
#else
format FailUnimpl {
@@ -701,7 +705,7 @@ decode OPCODE default Unknown::unknown() {
}}, IsNonSpeculative);
0x83: callsys({{
xc->syscall(R0);
}}, IsNonSpeculative);
}}, IsSerializeAfter, IsNonSpeculative);
// Read uniq reg into ABI return value register (r0)
0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);
// Write uniq reg with value from ABI arg register (r16)

View File

@@ -150,9 +150,6 @@ LinuxAlphaSystem::~LinuxAlphaSystem()
delete debugPrintkEvent;
delete idleStartEvent;
delete printThreadEvent;
delete intStartEvent;
delete intEndEvent;
delete intEndEvent2;
}
@@ -194,6 +191,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -212,6 +210,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -230,6 +230,7 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -112,6 +112,10 @@ namespace AlphaISA
lock_flag = 0;
lock_addr = 0;
}
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
#if FULL_SYSTEM
protected:
typedef uint64_t InternalProcReg;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
* Nathan Binkert
*/
#include "arch/alpha/ev5.hh"
@@ -220,6 +221,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> console;
@@ -238,6 +240,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -256,6 +260,7 @@ CREATE_SIM_OBJECT(AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
* Nathan Binkert
*/
#ifndef __ARCH_ALPHA_SYSTEM_HH__

View File

@@ -95,6 +95,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -113,6 +114,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -131,6 +134,7 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;

View File

@@ -52,8 +52,7 @@ base_sources = Split('''
# Full-system sources
full_system_sources = Split('''
memory.cc
mips34k.cc
#Insert Full-System Files Here
''')
# Syscall emulation (non-full-system) sources

View File

@@ -32,6 +32,10 @@
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
#if !FULL_SYSTEM
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace MipsISA
{
@@ -52,6 +56,12 @@ FaultName ArithmeticFault::_name = "arith";
FaultVect ArithmeticFault::_vect = 0x0501;
FaultStat ArithmeticFault::_count;
#if !FULL_SYSTEM
FaultName PageTableFault::_name = "page_table_fault";
FaultVect PageTableFault::_vect = 0x0000;
FaultStat PageTableFault::_count;
#endif
FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0101;
FaultStat InterruptFault::_count;
@@ -127,7 +137,28 @@ void ArithmeticFault::invoke(ThreadContext * tc)
panic("Arithmetic traps are unimplemented!");
}
#endif
#else //!FULL_SYSTEM
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
// address is higher than the stack region or in the current stack region
if (vaddr > p->stack_base || vaddr > p->stack_min)
FaultBase::invoke(tc);
// We've accessed the next page
if (vaddr > p->stack_min - PageBytes) {
p->stack_min -= PageBytes;
if (p->stack_base - p->stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
p->pTable->allocate(p->stack_min, PageBytes);
warn("Increasing stack size by one page.");
} else {
FaultBase::invoke(tc);
}
}
#endif
} // namespace MipsISA

View File

@@ -79,6 +79,30 @@ class AlignmentFault : public MipsFault
bool isAlignmentFault() {return true;}
};
#if !FULL_SYSTEM
class PageTableFault : public MipsFault
{
private:
Addr vaddr;
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
PageTableFault(Addr va)
: vaddr(va) {}
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
static inline Fault genPageTableFault(Addr va)
{
return new PageTableFault(va);
}
#endif
static inline Fault genMachineCheckFault()
{
return new MachineCheckFault;

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,6 @@ output header {{
using namespace MipsISA;
/**
* Base class for all MIPS static instructions.
*/

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -158,14 +158,16 @@ decode OPCODE_HI default Unknown::unknown() {
}
format HiLoMiscOp {
0x2: div({{
HI = Rs.sd % Rt.sd;
LO = Rs.sd / Rt.sd;
}});
0x3: divu({{
HI = Rs.ud % Rt.ud;
LO = Rs.ud / Rt.ud;
}});
0x2: div({{ if (Rt.sd != 0) {
HI = Rs.sd % Rt.sd;
LO = Rs.sd / Rt.sd;
}
}});
0x3: divu({{ if (Rt.ud != 0) {
HI = Rs.ud % Rt.ud;
LO = Rs.ud / Rt.ud;
}
}});
}
}
@@ -333,7 +335,7 @@ decode OPCODE_HI default Unknown::unknown() {
0x0: decode RS_HI {
0x0: decode RS_LO {
format CP1Control {
0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }});
0x0: mfc1 ({{ Rt.uw = Fs.uw; }});
0x2: cfc1({{
switch (FS)
@@ -438,9 +440,10 @@ decode OPCODE_HI default Unknown::unknown() {
0x3: div_s({{ Fd.sf = Fs.sf / Ft.sf;}});
0x4: sqrt_s({{ Fd.sf = sqrt(Fs.sf);}});
0x5: abs_s({{ Fd.sf = fabs(Fs.sf);}});
0x6: mov_s({{ Fd.sf = Fs.sf;}});
0x7: neg_s({{ Fd.sf = -Fs.sf;}});
}
0x6: BasicOp::mov_s({{ Fd.sf = Fs.sf;}});
}
0x1: decode FUNCTION_LO {
@@ -549,9 +552,10 @@ decode OPCODE_HI default Unknown::unknown() {
0x3: div_d({{ Fd.df = Fs.df / Ft.df; }});
0x4: sqrt_d({{ Fd.df = sqrt(Fs.df); }});
0x5: abs_d({{ Fd.df = fabs(Fs.df); }});
0x6: mov_d({{ Fd.df = Fs.df; }});
0x7: neg_d({{ Fd.df = -1 * Fs.df; }});
}
0x6: BasicOp::mov_d({{ Fd.df = Fs.df; }});
}
0x1: decode FUNCTION_LO {
@@ -853,17 +857,19 @@ decode OPCODE_HI default Unknown::unknown() {
0x3: decode FUNCTION_HI {
0x0: decode FUNCTION_LO {
format LoadIndexedMemory {
0x0: lwxc1({{ Ft.uw = Mem.uw;}});
0x1: ldxc1({{ Ft.ud = Mem.ud;}});
0x5: luxc1({{ Ft.uw = Mem.ud;}});
0x0: lwxc1({{ Fd.uw = Mem.uw;}});
0x1: ldxc1({{ Fd.ud = Mem.ud;}});
0x5: luxc1({{ Fd.ud = Mem.ud;}},
{{ EA = (Rs + Rt) & ~7; }});
}
}
0x1: decode FUNCTION_LO {
format StoreIndexedMemory {
0x0: swxc1({{ Mem.uw = Ft.uw;}});
0x1: sdxc1({{ Mem.ud = Ft.ud;}});
0x5: suxc1({{ Mem.ud = Ft.ud;}});
0x0: swxc1({{ Mem.uw = Fs.uw;}});
0x1: sdxc1({{ Mem.ud = Fs.ud;}});
0x5: suxc1({{ Mem.ud = Fs.ud;}},
{{ EA = (Rs + Rt) & ~7; }});
}
0x7: Prefetch::prefx({{ EA = Rs + Rt; }});
@@ -991,7 +997,7 @@ decode OPCODE_HI default Unknown::unknown() {
0x7: decode FUNCTION_HI {
0x0: decode FUNCTION_LO {
format BasicOp {
0x1: ext({{ Rt.uw = bits(Rs.uw, MSB+LSB, LSB); }});
0x0: ext({{ Rt.uw = bits(Rs.uw, MSB+LSB, LSB); }});
0x4: ins({{ Rt.uw = bits(Rt.uw, 31, MSB+1) << (MSB+1) |
bits(Rs.uw, MSB-LSB, 0) << LSB |
bits(Rt.uw, LSB-1, 0);
@@ -1014,8 +1020,8 @@ decode OPCODE_HI default Unknown::unknown() {
Rt.uw<7:0> << 8 |
Rt.uw<15:8>;
}});
0x10: seb({{ Rd.sw = Rt.sw<7:0>}});
0x18: seh({{ Rd.sw = Rt.sw<15:0>}});
0x10: seb({{ Rd.sw = Rt.sb; }});
0x18: seh({{ Rd.sw = Rt.sh; }});
}
}

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -142,10 +142,10 @@ output exec {{
cpu->setFloatRegBits(inst, 0, mips_nan, size);
//Read FCSR from FloatRegFile
uint32_t fcsr_bits = cpu->tc->readFloatRegBits(FCSR);
uint32_t fcsr_bits = cpu->tcBase()->readFloatRegBits(FCSR);
//Write FCSR from FloatRegFile
cpu->tc->setFloatRegBits(FCSR, genInvalidVector(fcsr_bits));
cpu->tcBase()->setFloatRegBits(FCSR, genInvalidVector(fcsr_bits));
if (traceData) { traceData->setData(mips_nan); }
return true;
@@ -158,12 +158,12 @@ output exec {{
fpResetCauseBits(%(CPU_exec_context)s *cpu)
{
//Read FCSR from FloatRegFile
uint32_t fcsr = cpu->tc->readFloatRegBits(FCSR);
uint32_t fcsr = cpu->tcBase()->readFloatRegBits(FCSR);
fcsr = bits(fcsr, 31, 18) << 18 | bits(fcsr, 11, 0);
//Write FCSR from FloatRegFile
cpu->tc->setFloatRegBits(FCSR, fcsr);
cpu->tcBase()->setFloatRegBits(FCSR, fcsr);
}
}};
@@ -176,8 +176,9 @@ def template FloatingPointExecute {{
//When is the right time to reset cause bits?
//start of every instruction or every cycle?
#if FULL_SYSTEM
fpResetCauseBits(xc);
#endif
%(op_decl)s;
%(op_rd)s;
@@ -192,7 +193,10 @@ def template FloatingPointExecute {{
//----
//Check for IEEE 754 FP Exceptions
//fault = fpNanOperands((FPOp*)this, xc, Fd, traceData);
if (!fpInvalidOp((FPOp*)this, xc, Fd, traceData) &&
if (
#if FULL_SYSTEM
!fpInvalidOp((FPOp*)this, xc, Fd, traceData) &&
#endif
fault == NoFault)
{
%(op_wb)s;

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -228,7 +228,7 @@ def format IntOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'IntOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = RegNopCheckDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
}};
@@ -236,7 +236,7 @@ def format IntImmOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'IntImmOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = ImmNopCheckDecode.subst(iop)
exec_output = BasicExecute.subst(iop)
}};
@@ -252,7 +252,7 @@ def format HiLoOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'HiLoOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = HiLoExecute.subst(iop)
}};
@@ -260,7 +260,7 @@ def format HiLoMiscOp(code, *opt_flags) {{
iop = InstObjParams(name, Name, 'HiLoMiscOp', CodeBlock(code), opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = OperateNopCheckDecode.subst(iop)
decode_block = BasicDecode.subst(iop)
exec_output = HiLoExecute.subst(iop)
}};

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2005 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -58,14 +58,8 @@ output header {{
StaticInstPtr _memAccPtr = nullStaticInstPtr)
: MipsStaticInst(mnem, _machInst, __opClass),
memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
disp(OFFSET)
disp(sext<16>(OFFSET))
{
//If Bit 15 is 1 then Sign Extend
int32_t temp = disp & 0x00008000;
if (temp > 0) {
disp |= 0xFFFF0000;
}
}
std::string
@@ -77,6 +71,24 @@ output header {{
const StaticInstPtr &memAccInst() const { return memAccPtr; }
};
/**
* Base class for a few miscellaneous memory-format insts
* that don't interpret the disp field
*/
class MemoryNoDisp : public Memory
{
protected:
/// Constructor
MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
StaticInstPtr _eaCompPtr = nullStaticInstPtr,
StaticInstPtr _memAccPtr = nullStaticInstPtr)
: Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
{
}
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
@@ -84,10 +96,18 @@ output decoder {{
std::string
Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
return csprintf("%-10s %c%d, %d(r%d)", mnemonic,
flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
}
std::string
MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %c%d, r%d(r%d)", mnemonic,
flags[IsFloating] ? 'f' : 'r',
flags[IsFloating] ? FD : RD,
RS, RT);
}
}};
def template LoadStoreDeclare {{
@@ -479,23 +499,11 @@ def template MiscCompleteAcc {{
}
}};
// load instructions use Rt as dest, so check for
// Rt == 0 to detect nops
def template LoadNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
if (RT == 0) {
i = makeNop(i);
}
return i;
}
}};
def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
decode_template = ImmNopCheckDecode,
exec_template_base = 'Load')
}};
@@ -510,7 +518,7 @@ def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
decode_template = ImmNopCheckDecode,
exec_template_base = 'Load')
}};
@@ -534,7 +542,7 @@ def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3;
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
decode_template = ImmNopCheckDecode,
exec_template_base = 'Load')
}};
@@ -551,7 +559,6 @@ def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3;
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
exec_template_base = 'Store')
}};

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -35,14 +35,15 @@
output header {{
/**
* Base class for integer operations.
* Base class for MIPS MT ASE operations.
*/
class MT : public MipsStaticInst
{
protected:
/// Constructor
MT(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
MT(const char *mnem, MachInst _machInst, OpClass __opClass) :
MipsStaticInst(mnem, _machInst, __opClass)
{
}

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -73,7 +73,8 @@ output decoder {{
MipsStaticInst *
makeNop(MipsStaticInst *inst)
{
MipsStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
std::string nop_str = "(" + inst->disassemble(0) + ")";
MipsStaticInst *nop = new Nop(nop_str, inst->machInst);
delete inst;
return nop;
}
@@ -87,16 +88,36 @@ output exec {{
}
}};
// integer & FP operate instructions use RT as dest, so check for
// RT == 0 to detect nops
// Int & FP operate instructions use RD as dest, so check for
// RD == 0 to detect nops
def template RegNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
//if (RD == 0) {
//i = makeNop(i);
//}
return i;
}
}};
def template OperateNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
//if (RD == 0) {
// i = makeNop(i);
// i = makeNop(i);
//}
return i;
}
}};
// IntImm & Memory instructions use Rt as dest, so check for
// Rt == 0 to detect nops
def template ImmNopCheckDecode {{
{
MipsStaticInst *i = new %(class_name)s(machInst);
//if (RT == 0) {
// i = makeNop(i);
// }
return i;
}
}};

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,7 @@ def template TrapExecute {{
}};
def format Trap(code, *flags) {{
code = 'panic(\"'
code = 'warn(\"'
code += 'Trap Exception Handler Is Currently Not Implemented.'
code += '\");'
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)

View File

@@ -1,7 +1,7 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2005 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2005 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2003-2006 The Regents of The University of Michigan
// Copyright (c) 2006 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -53,8 +53,8 @@ def operands {{
'R2': ('IntReg', 'uw','2', 'IsInteger', 5),
#Special Integer Reg operands
'HI': ('IntReg', 'uw','32', 'IsInteger', 6),
'LO': ('IntReg', 'uw','33', 'IsInteger', 7),
'HI': ('IntReg', 'uw','MipsISA::HI', 'IsInteger', 6),
'LO': ('IntReg', 'uw','MipsISA::LO', 'IsInteger', 7),
#Immediate Value operand
'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
@@ -66,11 +66,11 @@ def operands {{
'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3),
#Special Floating Point Control Reg Operands
'FIR': ('FloatReg', 'uw', '32', 'IsFloating', 1),
'FCCR': ('FloatReg', 'uw', '33', 'IsFloating', 2),
'FEXR': ('FloatReg', 'uw', '34', 'IsFloating', 3),
'FENR': ('FloatReg', 'uw', '35', 'IsFloating', 3),
'FCSR': ('FloatReg', 'uw', '36', 'IsFloating', 3),
'FIR': ('FloatReg', 'uw', 'MipsISA::FIR', 'IsFloating', 1),
'FCCR': ('FloatReg', 'uw', 'MipsISA::FCCR', 'IsFloating', 2),
'FEXR': ('FloatReg', 'uw', 'MipsISA::FEXR', 'IsFloating', 3),
'FENR': ('FloatReg', 'uw', 'MipsISA::FENR', 'IsFloating', 3),
'FCSR': ('FloatReg', 'uw', 'MipsISA::FCSR', 'IsFloating', 3),
#Operands For Paired Singles FP Operations
'Fd1': ('FloatReg', 'sf', 'FD', 'IsFloating', 4),

View File

@@ -30,7 +30,7 @@
*/
#include "arch/mips/isa_traits.hh"
#include "config/full_system.hh"
//#include "config/full_system.hh"
#include "cpu/static_inst.hh"
#include "sim/serialize.hh"
#include "base/bitfield.hh"
@@ -43,39 +43,20 @@ void
MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
{
panic("Copy Regs Not Implemented Yet\n");
/*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag);
}
#if FULL_SYSTEM
copyIprs(xc);
#endif*/
void
MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
}
void
MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
/*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
lock_addr = xc->readMiscReg(MipsISA::Lock_Addr_DepTag);
#endif*/
}
#if FULL_SYSTEM
static inline Addr
TruncPage(Addr addr)
{ return addr & ~(MipsISA::PageBytes - 1); }
static inline Addr
RoundPage(Addr addr)
{ return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); }
#endif
void
IntRegFile::serialize(std::ostream &os)
{
@@ -100,12 +81,6 @@ RegFile::serialize(std::ostream &os)
SERIALIZE_SCALAR(pc);
SERIALIZE_SCALAR(npc);
SERIALIZE_SCALAR(nnpc);
#if FULL_SYSTEM
SERIALIZE_ARRAY(palregs, NumIntRegs);
SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
SERIALIZE_SCALAR(intrflag);
SERIALIZE_SCALAR(pal_shadow);
#endif
}
@@ -121,43 +96,5 @@ RegFile::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(pc);
UNSERIALIZE_SCALAR(npc);
UNSERIALIZE_SCALAR(nnpc);
#if FULL_SYSTEM
UNSERIALIZE_ARRAY(palregs, NumIntRegs);
UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
UNSERIALIZE_SCALAR(intrflag);
UNSERIALIZE_SCALAR(pal_shadow);
#endif
}
#if FULL_SYSTEM
void
PTE::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(tag);
SERIALIZE_SCALAR(ppn);
SERIALIZE_SCALAR(xre);
SERIALIZE_SCALAR(xwe);
SERIALIZE_SCALAR(asn);
SERIALIZE_SCALAR(asma);
SERIALIZE_SCALAR(fonr);
SERIALIZE_SCALAR(fonw);
SERIALIZE_SCALAR(valid);
}
void
PTE::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(tag);
UNSERIALIZE_SCALAR(ppn);
UNSERIALIZE_SCALAR(xre);
UNSERIALIZE_SCALAR(xwe);
UNSERIALIZE_SCALAR(asn);
UNSERIALIZE_SCALAR(asma);
UNSERIALIZE_SCALAR(fonr);
UNSERIALIZE_SCALAR(fonw);
UNSERIALIZE_SCALAR(valid);
}
#endif //FULL_SYSTEM

View File

@@ -57,12 +57,6 @@ namespace LittleEndianGuest {};
class StaticInst;
class StaticInstPtr;
namespace MIPS34K {
int DTB_ASN_ASN(uint64_t reg);
int ITB_ASN_ASN(uint64_t reg);
};
#if !FULL_SYSTEM
class SyscallReturn {
public:
template <class T>
@@ -95,7 +89,6 @@ class SyscallReturn {
uint64_t retval;
bool success;
};
#endif
namespace MipsISA
{
@@ -136,16 +129,10 @@ namespace MipsISA
template <class TC>
void zeroRegisters(TC *tc);
const Addr MaxAddr = (Addr)-1;
// const Addr MaxAddr = (Addr)-1;
void copyRegs(ThreadContext *src, ThreadContext *dest);
uint64_t fpConvert(double fp_val, ConvertType cvt_type);
double roundFP(double val, int digits);
double truncFP(double val);
bool getFPConditionCode(uint32_t fcsr_reg, int cc);
uint32_t makeCCVector(uint32_t fcsr, int num, bool val);
// Machine operations
void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
@@ -191,12 +178,6 @@ namespace MipsISA
};
#if FULL_SYSTEM
#include "arch/mips/mips34k.hh"
#endif
using namespace MipsISA;
#endif // __ARCH_MIPS_ISA_TRAITS_HH__

View File

@@ -1,3 +1,4 @@
/*
* Copyright (c) 2003-2004 The Regents of The University of Michigan
* All rights reserved.
@@ -40,6 +41,8 @@
using namespace std;
using namespace MipsISA;
Addr MipsLiveProcess::stack_start = 0x7FFFFFFF;
MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv, std::vector<std::string> &envp)
@@ -48,10 +51,11 @@ MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
{
// Set up stack. On MIPS, stack starts at the top of kuseg
// user address space. MIPS stack grows down from here
stack_base = 0x7FFFFFFF;
stack_base = stack_start;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
stack_start = next_thread_stack_base;
// Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();

View File

@@ -50,6 +50,9 @@ class MipsLiveProcess : public LiveProcess
std::vector<std::string> &envp);
void startup();
static Addr stack_start;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,8 +24,6 @@
* 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: Korey Sewell
*/
#ifndef __ARCH_MIPS_FLOAT_REGFILE_HH__
@@ -34,13 +32,14 @@
#include "arch/mips/types.hh"
#include "arch/mips/constants.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
#include "config/full_system.hh"
#include "sim/byteswap.hh"
#include "sim/faults.hh"
#include "sim/host.hh"
class Checkpoint;
class ThreadContext;
class ExecContext;
class Regfile;
namespace MipsISA
@@ -101,8 +100,9 @@ namespace MipsISA
}
}
Fault setReg(int floatReg, const FloatReg &val, int width)
Fault setReg(int floatReg, const FloatRegVal &val, int width)
{
using namespace std;
switch(width)
{
case SingleWidth:
@@ -117,8 +117,8 @@ namespace MipsISA
{
const void *double_ptr = &val;
FloatReg64 temp_double = *(FloatReg64 *) double_ptr;
regs[floatReg + 1] = temp_double >> 32;
regs[floatReg] = 0x0000FFFF & temp_double;
regs[floatReg + 1] = bits(temp_double, 63, 32);
regs[floatReg] = bits(temp_double, 31, 0);
break;
}
@@ -140,8 +140,8 @@ namespace MipsISA
break;
case DoubleWidth:
regs[floatReg + 1] = val >> 32;
regs[floatReg] = val;
regs[floatReg + 1] = bits(val, 63, 32);
regs[floatReg] = bits(val, 31, 0);
break;
default:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -65,11 +65,6 @@ namespace MipsISA
};
enum MiscIntRegNums {
HI = NumIntArchRegs,
LO
};
} // namespace MipsISA
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,18 +45,12 @@ namespace MipsISA
protected:
uint64_t fpcr; // floating point condition codes
uint64_t uniq; // process-unique register
bool lock_flag; // lock flag for LL/SC
Addr lock_addr; // lock address for LL/SC
MiscReg miscRegFile[NumMiscRegs];
public:
//These functions should be removed once the simplescalar cpu model
//has been replaced.
int getInstAsid();
int getDataAsid();
void copyMiscRegs(ThreadContext *tc);
MiscReg readReg(int misc_reg)
@@ -80,17 +74,6 @@ namespace MipsISA
miscRegFile[misc_reg] = val; return NoFault;
}
#if FULL_SYSTEM
void clearIprs() { }
protected:
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
private:
MiscReg readIpr(int idx, Fault &fault, ThreadContext *tc) { }
Fault setIpr(int idx, uint64_t val, ThreadContext *tc) { }
#endif
friend class RegFile;
};
} // namespace MipsISA

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -81,12 +81,12 @@ namespace MipsISA
return miscRegFile.setRegWithEffect(miscReg, val, tc);
}
FloatReg readFloatReg(int floatReg)
FloatRegVal readFloatReg(int floatReg)
{
return floatRegFile.readReg(floatReg,SingleWidth);
}
FloatReg readFloatReg(int floatReg, int width)
FloatRegVal readFloatReg(int floatReg, int width)
{
return floatRegFile.readReg(floatReg,width);
}
@@ -101,12 +101,12 @@ namespace MipsISA
return floatRegFile.readRegBits(floatReg,width);
}
Fault setFloatReg(int floatReg, const FloatReg &val)
Fault setFloatReg(int floatReg, const FloatRegVal &val)
{
return floatRegFile.setReg(floatReg, val, SingleWidth);
}
Fault setFloatReg(int floatReg, const FloatReg &val, int width)
Fault setFloatReg(int floatReg, const FloatRegVal &val, int width)
{
return floatRegFile.setReg(floatReg, val, width);
}
@@ -168,16 +168,6 @@ namespace MipsISA
nnpc = val;
}
#if FULL_SYSTEM
IntReg palregs[NumIntRegs]; // PAL shadow registers
InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
int intrflag; // interrupt flag
bool pal_shadow; // using pal_shadow registers
inline int instAsid() { return MIPS34K::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); }
inline int dataAsid() { return MIPS34K::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }
#endif // FULL_SYSTEM
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
@@ -193,9 +183,6 @@ namespace MipsISA
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
#if FULL_SYSTEM
void copyIprs(ThreadContext *src, ThreadContext *dest);
#endif
} // namespace MipsISA
#endif

View File

@@ -25,11 +25,11 @@
* (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: Korey Sewell
* Authors: Ali Saidi
*/
#ifndef __ARCH_ALPHA_STACKTRACE_HH__
#define __ARCH_ALPHA_STACKTRACE_HH__
#ifndef __ARCH_MIPS_STACKTRACE_HH__
#define __ARCH_MIPS_STACKTRACE_HH__
#include "base/trace.hh"
#include "cpu/static_inst.hh"
@@ -118,4 +118,4 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
return true;
}
#endif // __ARCH_ALPHA_STACKTRACE_HH__
#endif // __ARCH_MIPS_STACKTRACE_HH__

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,14 +42,15 @@ namespace MipsISA
typedef uint32_t IntReg;
// floating point register file entry type
typedef double FloatReg;
typedef uint32_t FloatReg32;
typedef uint64_t FloatReg64;
typedef uint64_t FloatRegBits;
typedef double FloatRegVal;
typedef double FloatReg;
// cop-0/cop-1 system control register
typedef uint64_t MiscReg;
typedef uint64_t InternalProcReg;
typedef union {
IntReg intreg;

View File

@@ -33,6 +33,10 @@
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
#if !FULL_SYSTEM
#include "sim/process.hh"
#include "mem/page_table.hh"
#endif
namespace SparcISA
{
@@ -218,6 +222,13 @@ TrapType TrapInstruction::_baseTrapType = 0x100;
FaultPriority TrapInstruction::_priority = 16;
FaultStat TrapInstruction::_count;
#if !FULL_SYSTEM
FaultName PageTableFault::_name = "page_table_fault";
TrapType PageTableFault::_trapType = 0x0000;
FaultPriority PageTableFault::_priority = 0;
FaultStat PageTableFault::_count;
#endif
#if FULL_SYSTEM
void SparcFault::invoke(ThreadContext * tc)
@@ -249,9 +260,28 @@ void SparcFault::invoke(ThreadContext * tc)
void TrapInstruction::invoke(ThreadContext * tc)
{
tc->syscall(syscall_num);
// Should be handled in ISA.
}
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
// address is higher than the stack region or in the current stack region
if (vaddr > p->stack_base || vaddr > p->stack_min)
FaultBase::invoke(tc);
// We've accessed the next page
if (vaddr > p->stack_min - PageBytes) {
p->stack_min -= PageBytes;
if (p->stack_base - p->stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
p->pTable->allocate(p->stack_min, PageBytes);
warn("Increasing stack size by one page.");
} else {
FaultBase::invoke(tc);
}
}
#endif
} // namespace SparcISA

View File

@@ -83,6 +83,31 @@ class MemAddressNotAligned : public SparcFault
bool isAlignmentFault() {return true;}
};
#if !FULL_SYSTEM
class PageTableFault : public SparcFault
{
private:
Addr vaddr;
static FaultName _name;
static TrapType _trapType;
static FaultPriority _priority;
static FaultStat _count;
public:
PageTableFault(Addr va)
: vaddr(va) {}
FaultName name() {return _name;}
TrapType trapType() {return _trapType;}
FaultPriority priority() {return _priority;}
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
static inline Fault genPageTableFault(Addr va)
{
return new PageTableFault(va);
}
#endif
static inline Fault genMachineCheckFault()
{
return new InternalProcessorError;
@@ -589,6 +614,7 @@ class TrapInstruction : public EnumeratedFault
#endif
};
} // SparcISA namespace
#endif // __FAULTS_HH__

View File

@@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> reset_bin;
@@ -161,6 +162,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(reset_bin, "file that contains the reset code"),
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
@@ -183,6 +186,7 @@ CREATE_SIM_OBJECT(SparcSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->reset_bin = reset_bin;
p->hypervisor_bin = hypervisor_bin;

View File

@@ -180,13 +180,11 @@ FastAlloc::dump_oldest(int n)
// C interfaces to FastAlloc::dump_summary() and FastAlloc::dump_oldest().
// gdb seems to have trouble with calling C++ functions directly.
//
extern "C" void
fast_alloc_summary()
{
FastAlloc::dump_summary();
}
extern "C" void
fast_alloc_oldest(int n)
{
FastAlloc::dump_oldest(n);

View File

@@ -25,7 +25,8 @@
* (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: Kevin Lim
* Authors: Nathan Binkert
* Kevin Lim
*/
#ifndef __BASE_TIMEBUF_HH__
@@ -214,6 +215,11 @@ class TimeBuffer
{
return wire(this, 0);
}
int getSize()
{
return size;
}
};
#endif // __BASE_TIMEBUF_HH__

View File

@@ -247,7 +247,6 @@ DebugOut()
//
// Dump trace buffer to specified file (cout if NULL)
//
extern "C"
void
dumpTrace(const char *filename)
{
@@ -269,7 +268,6 @@ dumpTrace(const char *filename)
// same facility as the "trace to file" feature, and will print error
// messages rather than clobbering an existing ostream pointer.
//
extern "C"
void
echoTrace(bool on)
{
@@ -289,7 +287,6 @@ echoTrace(bool on)
}
}
extern "C"
void
printTraceFlags()
{
@@ -338,14 +335,12 @@ tweakTraceFlag(const char *string, bool value)
cprintf("could not find flag %s\n", string);
}
extern "C"
void
setTraceFlag(const char *string)
{
tweakTraceFlag(string, true);
}
extern "C"
void
clearTraceFlag(const char *string)
{

View File

@@ -48,8 +48,10 @@ ccfilename = sys.argv[1] + '.cc'
# To define a new flag, simply add it to this list.
#
baseFlags = [
'Activity',
'AlphaConsole',
'BADADDR',
'BE',
'BPredRAS',
'Bus',
'BusAddrRanges',
@@ -84,6 +86,7 @@ baseFlags = [
'EthernetPIO',
'EthernetSM',
'Event',
'FE',
'Fault',
'Fetch',
'Flow',
@@ -97,6 +100,7 @@ baseFlags = [
'GDBSend',
'GDBWrite',
'HWPrefetch',
'IBE',
'IEW',
'IIC',
'IICMore',
@@ -115,10 +119,8 @@ baseFlags = [
'MSHR',
'Mbox',
'MemDepUnit',
'O3CPU',
'OzoneCPU',
'FE',
'IBE',
'BE',
'OzoneLSQ',
'PCEvent',
'PCIA',
@@ -132,6 +134,7 @@ baseFlags = [
'RenameMap',
'SQL',
'Sampler',
'Scoreboard',
'ScsiCtrl',
'ScsiDisk',
'ScsiNone',
@@ -155,8 +158,6 @@ baseFlags = [
'Uart',
'VtoPhys',
'WriteBarrier',
'Activity',
'Scoreboard',
'Writeback',
]
@@ -175,7 +176,7 @@ compoundFlagMap = {
'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
'FullCPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'Activity','Scoreboard','Writeback'],
'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'O3CPU', 'Activity','Scoreboard','Writeback'],
'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU']
}

View File

@@ -68,6 +68,13 @@ mem_comp_sig_template = '''
virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; };
'''
# Generate a temporary CPU list, including the CheckerCPU if
# it's enabled. This isn't used for anything else other than StaticInst
# headers.
temp_cpu_list = env['CPU_MODELS']
if env['USE_CHECKER']:
temp_cpu_list.append('CheckerCPU')
# Generate header.
def gen_cpu_exec_signatures(target, source, env):
f = open(str(target[0]), 'w')
@@ -75,7 +82,7 @@ def gen_cpu_exec_signatures(target, source, env):
#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__
#define __CPU_STATIC_INST_EXEC_SIGS_HH__
'''
for cpu in env['CPU_MODELS']:
for cpu in temp_cpu_list:
xc_type = CpuModel.dict[cpu].strings['CPU_exec_context']
print >> f, exec_sig_template % (xc_type, xc_type, xc_type)
print >> f, '''
@@ -85,12 +92,19 @@ def gen_cpu_exec_signatures(target, source, env):
# Generate string that gets printed when header is rebuilt
def gen_sigs_string(target, source, env):
return "Generating static_inst_exec_sigs.hh: " \
+ ', '.join(env['CPU_MODELS'])
+ ', '.join(temp_cpu_list)
# Add command to generate header to environment.
env.Command('static_inst_exec_sigs.hh', models_db,
Action(gen_cpu_exec_signatures, gen_sigs_string,
varlist = ['CPU_MODELS']))
varlist = temp_cpu_list))
env.Depends('static_inst_exec_sigs.hh', Value(env['USE_CHECKER']))
env.Depends('static_inst_exec_sigs.hh', Value(env['CPU_MODELS']))
# List of suppported CPUs by the Checker. Errors out if USE_CHECKER=True
# and one of these are not being used.
CheckerSupportedCPUList = ['O3CPU', 'OzoneCPU']
#################################################################
#
@@ -116,15 +130,13 @@ if need_simple_base:
if 'FastCPU' in env['CPU_MODELS']:
sources += Split('fast/cpu.cc')
if 'AlphaFullCPU' in env['CPU_MODELS']:
need_bp_unit = False
if 'O3CPU' in env['CPU_MODELS']:
need_bp_unit = True
sources += SConscript('o3/SConscript', exports = 'env')
sources += Split('''
base_dyn_inst.cc
o3/2bit_local_pred.cc
o3/alpha_dyn_inst.cc
o3/alpha_cpu.cc
o3/alpha_cpu_builder.cc
o3/base_dyn_inst.cc
o3/bpred_unit.cc
o3/btb.cc
o3/commit.cc
o3/decode.cc
o3/fetch.cc
@@ -136,40 +148,54 @@ if 'AlphaFullCPU' in env['CPU_MODELS']:
o3/lsq_unit.cc
o3/lsq.cc
o3/mem_dep_unit.cc
o3/ras.cc
o3/rename.cc
o3/rename_map.cc
o3/rob.cc
o3/scoreboard.cc
o3/store_set.cc
o3/tournament_pred.cc
''')
if env['USE_CHECKER']:
sources += Split('o3/checker_builder.cc')
if 'OzoneSimpleCPU' in env['CPU_MODELS']:
if 'OzoneCPU' in env['CPU_MODELS']:
need_bp_unit = True
sources += Split('''
ozone/base_dyn_inst.cc
ozone/bpred_unit.cc
ozone/cpu.cc
ozone/cpu_builder.cc
ozone/dyn_inst.cc
ozone/front_end.cc
ozone/inorder_back_end.cc
ozone/inst_queue.cc
ozone/rename_table.cc
''')
if 'OzoneCPU' in env['CPU_MODELS']:
sources += Split('''
ozone/lsq_unit.cc
ozone/lw_back_end.cc
ozone/lw_lsq.cc
ozone/rename_table.cc
''')
if env['USE_CHECKER']:
sources += Split('ozone/checker_builder.cc')
if 'CheckerCPU' in env['CPU_MODELS']:
if need_bp_unit:
sources += Split('''
checker/cpu.cc
checker/o3_cpu_builder.cc
o3/2bit_local_pred.cc
o3/btb.cc
o3/ras.cc
o3/tournament_pred.cc
''')
# FullCPU sources are included from m5/SConscript since they're not
if env['USE_CHECKER']:
sources += Split('checker/cpu.cc')
checker_supports = False
for i in CheckerSupportedCPUList:
if i in env['CPU_MODELS']:
checker_supports = True
if not checker_supports:
print "Checker only supports CPU models",
for i in CheckerSupportedCPUList:
print i,
print ", please set USE_CHECKER=False or use one of those CPU models"
Exit(1)
# FullCPU sources are included from src/SConscript since they're not
# below this point in the file hierarchy.
# Convert file names to SCons File objects. This takes care of the

View File

@@ -41,7 +41,6 @@
#include "cpu/cpuevent.hh"
#include "cpu/thread_context.hh"
#include "cpu/profile.hh"
#include "cpu/sampler/sampler.hh"
#include "sim/param.hh"
#include "sim/process.hh"
#include "sim/sim_events.hh"
@@ -60,11 +59,11 @@ int maxThreadsPerCPU = 1;
#if FULL_SYSTEM
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), checkInterrupts(true),
: MemObject(p->name), clock(p->clock), checkInterrupts(true),
params(p), number_of_threads(p->numberOfThreads), system(p->system)
#else
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), params(p),
: MemObject(p->name), clock(p->clock), params(p),
number_of_threads(p->numberOfThreads), system(p->system)
#endif
{
@@ -237,7 +236,7 @@ BaseCPU::registerThreadContexts()
void
BaseCPU::switchOut(Sampler *sampler)
BaseCPU::switchOut()
{
panic("This CPU doesn't support sampling!");
}

View File

@@ -36,17 +36,17 @@
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "cpu/sampler/sampler.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
#include "mem/mem_object.hh"
#include "arch/isa_traits.hh"
class BranchPred;
class CheckerCPU;
class ThreadContext;
class System;
class Port;
class BaseCPU : public SimObject
class BaseCPU : public MemObject
{
protected:
// CPU's clock period in terms of the number of ticks of curTime.
@@ -148,7 +148,7 @@ class BaseCPU : public SimObject
/// Prepare for another CPU to take over execution. When it is
/// is ready (drained pipe) it signals the sampler.
virtual void switchOut(Sampler *);
virtual void switchOut();
/// Take over execution from the given CPU. Used for warm-up and
/// sampling.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
#ifndef __CPU_BASE_DYN_INST_HH__
#define __CPU_BASE_DYN_INST_HH__
#include <bitset>
#include <list>
#include <string>
@@ -44,12 +45,6 @@
#include "cpu/static_inst.hh"
#include "mem/packet.hh"
#include "sim/system.hh"
/*
#include "encumbered/cpu/full/bpred_update.hh"
#include "encumbered/cpu/full/spec_memory.hh"
#include "encumbered/cpu/full/spec_state.hh"
#include "encumbered/mem/functional/main.hh"
*/
/**
* @file
@@ -64,8 +59,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
{
public:
// Typedef for the CPU.
typedef typename Impl::FullCPU FullCPU;
typedef typename FullCPU::ImplState ImplState;
typedef typename Impl::CPUType ImplCPU;
typedef typename ImplCPU::ImplState ImplState;
// Binary machine instruction type.
typedef TheISA::MachInst MachInst;
@@ -132,56 +127,34 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** The sequence number of the instruction. */
InstSeqNum seqNum;
/** Is the instruction in the IQ */
bool iqEntry;
enum Status {
IqEntry, /// Instruction is in the IQ
RobEntry, /// Instruction is in the ROB
LsqEntry, /// Instruction is in the LSQ
Completed, /// Instruction has completed
ResultReady, /// Instruction has its result
CanIssue, /// Instruction can issue and execute
Issued, /// Instruction has issued
Executed, /// Instruction has executed
CanCommit, /// Instruction can commit
AtCommit, /// Instruction has reached commit
Committed, /// Instruction has committed
Squashed, /// Instruction is squashed
SquashedInIQ, /// Instruction is squashed in the IQ
SquashedInLSQ, /// Instruction is squashed in the LSQ
SquashedInROB, /// Instruction is squashed in the ROB
RecoverInst, /// Is a recover instruction
BlockingInst, /// Is a blocking instruction
ThreadsyncWait, /// Is a thread synchronization instruction
SerializeBefore, /// Needs to serialize on
/// instructions ahead of it
SerializeAfter, /// Needs to serialize instructions behind it
SerializeHandled, /// Serialization has been handled
NumStatus
};
/** Is the instruction in the ROB */
bool robEntry;
/** Is the instruction in the LSQ */
bool lsqEntry;
/** Is the instruction completed. */
bool completed;
/** Is the instruction's result ready. */
bool resultReady;
/** Can this instruction issue. */
bool canIssue;
/** Has this instruction issued. */
bool issued;
/** Has this instruction executed (or made it through execute) yet. */
bool executed;
/** Can this instruction commit. */
bool canCommit;
/** Is this instruction committed. */
bool committed;
/** Is this instruction squashed. */
bool squashed;
/** Is this instruction squashed in the instruction queue. */
bool squashedInIQ;
/** Is this instruction squashed in the instruction queue. */
bool squashedInLSQ;
/** Is this instruction squashed in the instruction queue. */
bool squashedInROB;
/** Is this a recover instruction. */
bool recoverInst;
/** Is this a thread blocking instruction. */
bool blockingInst; /* this inst has called thread_block() */
/** Is this a thread syncrhonization instruction. */
bool threadsyncWait;
/** The status of this BaseDynInst. Several bits can be set. */
std::bitset<NumStatus> status;
/** The thread this instruction is from. */
short threadNumber;
@@ -192,8 +165,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** How many source registers are ready. */
unsigned readyRegs;
/** Pointer to the FullCPU object. */
FullCPU *cpu;
/** Pointer to the Impl's CPU object. */
ImplCPU *cpu;
/** Pointer to the thread state. */
ImplState *thread;
@@ -202,10 +175,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
Fault fault;
/** The memory request. */
// MemReqPtr req;
Request *req;
// Packet pkt;
/** Pointer to the data for the memory access. */
uint8_t *memData;
/** The effective virtual address (lds & stores only). */
@@ -223,12 +195,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** The memory request flags (from translation). */
unsigned memReqFlags;
/** The size of the data to be stored. */
int storeSize;
/** The data to be stored. */
IntReg storeData;
union Result {
uint64_t integer;
float fp;
@@ -273,7 +239,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
* @param cpu Pointer to the instruction's CPU.
*/
BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num,
FullCPU *cpu);
ImplCPU *cpu);
/** BaseDynInst constructor given a StaticInst pointer.
* @param _staticInst The StaticInst for this BaseDynInst.
@@ -288,21 +254,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
void initVars();
public:
/**
* @todo: Make this function work; currently it is a dummy function.
* @param fault Last fault.
* @param cmd Last command.
* @param addr Virtual address of access.
* @param p Memory accessed.
* @param nbytes Access size.
*/
// void
// trace_mem(Fault fault,
// MemCmd cmd,
// Addr addr,
// void *p,
// int nbytes);
/** Dumps out contents of this BaseDynInst. */
void dump();
@@ -360,9 +311,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
bool isThreadSync() const { return staticInst->isThreadSync(); }
bool isSerializing() const { return staticInst->isSerializing(); }
bool isSerializeBefore() const
{ return staticInst->isSerializeBefore() || serializeBefore; }
{ return staticInst->isSerializeBefore() || status[SerializeBefore]; }
bool isSerializeAfter() const
{ return staticInst->isSerializeAfter() || serializeAfter; }
{ return staticInst->isSerializeAfter() || status[SerializeAfter]; }
bool isMemBarrier() const { return staticInst->isMemBarrier(); }
bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
@@ -371,41 +322,32 @@ class BaseDynInst : public FastAlloc, public RefCounted
bool isUnverifiable() const { return staticInst->isUnverifiable(); }
/** Temporarily sets this instruction as a serialize before instruction. */
void setSerializeBefore() { serializeBefore = true; }
void setSerializeBefore() { status.set(SerializeBefore); }
/** Clears the serializeBefore part of this instruction. */
void clearSerializeBefore() { serializeBefore = false; }
void clearSerializeBefore() { status.reset(SerializeBefore); }
/** Checks if this serializeBefore is only temporarily set. */
bool isTempSerializeBefore() { return serializeBefore; }
/** Tracks if instruction has been externally set as serializeBefore. */
bool serializeBefore;
bool isTempSerializeBefore() { return status[SerializeBefore]; }
/** Temporarily sets this instruction as a serialize after instruction. */
void setSerializeAfter() { serializeAfter = true; }
void setSerializeAfter() { status.set(SerializeAfter); }
/** Clears the serializeAfter part of this instruction.*/
void clearSerializeAfter() { serializeAfter = false; }
void clearSerializeAfter() { status.reset(SerializeAfter); }
/** Checks if this serializeAfter is only temporarily set. */
bool isTempSerializeAfter() { return serializeAfter; }
bool isTempSerializeAfter() { return status[SerializeAfter]; }
/** Tracks if instruction has been externally set as serializeAfter. */
bool serializeAfter;
/** Sets the serialization part of this instruction as handled. */
void setSerializeHandled() { status.set(SerializeHandled); }
/** Checks if the serialization part of this instruction has been
* handled. This does not apply to the temporary serializing
* state; it only applies to this instruction's own permanent
* serializing state.
*/
bool isSerializeHandled() { return serializeHandled; }
/** Sets the serialization part of this instruction as handled. */
void setSerializeHandled() { serializeHandled = true; }
/** Whether or not the serialization of this instruction has been handled. */
bool serializeHandled;
bool isSerializeHandled() { return status[SerializeHandled]; }
/** Returns the opclass of this instruction. */
OpClass opClass() const { return staticInst->opClass(); }
@@ -439,11 +381,13 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Returns the result of a floating point (double) instruction. */
double readDoubleResult() { return instResult.dbl; }
/** Records an integer register being set to a value. */
void setIntReg(const StaticInst *si, int idx, uint64_t val)
{
instResult.integer = val;
}
/** Records an fp register being set to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
{
if (width == 32)
@@ -454,16 +398,19 @@ class BaseDynInst : public FastAlloc, public RefCounted
panic("Unsupported width!");
}
/** Records an fp register being set to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val)
{
instResult.fp = val;
}
/** Records an fp register being set to an integer value. */
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val, int width)
{
instResult.integer = val;
}
/** Records an fp register being set to an integer value. */
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val)
{
instResult.integer = val;
@@ -482,106 +429,112 @@ class BaseDynInst : public FastAlloc, public RefCounted
}
/** Sets this instruction as completed. */
void setCompleted() { completed = true; }
void setCompleted() { status.set(Completed); }
/** Returns whether or not this instruction is completed. */
bool isCompleted() const { return completed; }
bool isCompleted() const { return status[Completed]; }
void setResultReady() { resultReady = true; }
/** Marks the result as ready. */
void setResultReady() { status.set(ResultReady); }
bool isResultReady() const { return resultReady; }
/** Returns whether or not the result is ready. */
bool isResultReady() const { return status[ResultReady]; }
/** Sets this instruction as ready to issue. */
void setCanIssue() { canIssue = true; }
void setCanIssue() { status.set(CanIssue); }
/** Returns whether or not this instruction is ready to issue. */
bool readyToIssue() const { return canIssue; }
bool readyToIssue() const { return status[CanIssue]; }
/** Sets this instruction as issued from the IQ. */
void setIssued() { issued = true; }
void setIssued() { status.set(Issued); }
/** Returns whether or not this instruction has issued. */
bool isIssued() const { return issued; }
bool isIssued() const { return status[Issued]; }
/** Sets this instruction as executed. */
void setExecuted() { executed = true; }
void setExecuted() { status.set(Executed); }
/** Returns whether or not this instruction has executed. */
bool isExecuted() const { return executed; }
bool isExecuted() const { return status[Executed]; }
/** Sets this instruction as ready to commit. */
void setCanCommit() { canCommit = true; }
void setCanCommit() { status.set(CanCommit); }
/** Clears this instruction as being ready to commit. */
void clearCanCommit() { canCommit = false; }
void clearCanCommit() { status.reset(CanCommit); }
/** Returns whether or not this instruction is ready to commit. */
bool readyToCommit() const { return canCommit; }
bool readyToCommit() const { return status[CanCommit]; }
void setAtCommit() { status.set(AtCommit); }
bool isAtCommit() { return status[AtCommit]; }
/** Sets this instruction as committed. */
void setCommitted() { committed = true; }
void setCommitted() { status.set(Committed); }
/** Returns whether or not this instruction is committed. */
bool isCommitted() const { return committed; }
bool isCommitted() const { return status[Committed]; }
/** Sets this instruction as squashed. */
void setSquashed() { squashed = true; }
void setSquashed() { status.set(Squashed); }
/** Returns whether or not this instruction is squashed. */
bool isSquashed() const { return squashed; }
bool isSquashed() const { return status[Squashed]; }
//Instruction Queue Entry
//-----------------------
/** Sets this instruction as a entry the IQ. */
void setInIQ() { iqEntry = true; }
void setInIQ() { status.set(IqEntry); }
/** Sets this instruction as a entry the IQ. */
void removeInIQ() { iqEntry = false; }
/** Sets this instruction as squashed in the IQ. */
void setSquashedInIQ() { squashedInIQ = true; squashed = true;}
/** Returns whether or not this instruction is squashed in the IQ. */
bool isSquashedInIQ() const { return squashedInIQ; }
void clearInIQ() { status.reset(IqEntry); }
/** Returns whether or not this instruction has issued. */
bool isInIQ() const { return iqEntry; }
bool isInIQ() const { return status[IqEntry]; }
/** Sets this instruction as squashed in the IQ. */
void setSquashedInIQ() { status.set(SquashedInIQ); status.set(Squashed);}
/** Returns whether or not this instruction is squashed in the IQ. */
bool isSquashedInIQ() const { return status[SquashedInIQ]; }
//Load / Store Queue Functions
//-----------------------
/** Sets this instruction as a entry the LSQ. */
void setInLSQ() { lsqEntry = true; }
void setInLSQ() { status.set(LsqEntry); }
/** Sets this instruction as a entry the LSQ. */
void removeInLSQ() { lsqEntry = false; }
/** Sets this instruction as squashed in the LSQ. */
void setSquashedInLSQ() { squashedInLSQ = true;}
/** Returns whether or not this instruction is squashed in the LSQ. */
bool isSquashedInLSQ() const { return squashedInLSQ; }
void removeInLSQ() { status.reset(LsqEntry); }
/** Returns whether or not this instruction is in the LSQ. */
bool isInLSQ() const { return lsqEntry; }
bool isInLSQ() const { return status[LsqEntry]; }
/** Sets this instruction as squashed in the LSQ. */
void setSquashedInLSQ() { status.set(SquashedInLSQ);}
/** Returns whether or not this instruction is squashed in the LSQ. */
bool isSquashedInLSQ() const { return status[SquashedInLSQ]; }
//Reorder Buffer Functions
//-----------------------
/** Sets this instruction as a entry the ROB. */
void setInROB() { robEntry = true; }
void setInROB() { status.set(RobEntry); }
/** Sets this instruction as a entry the ROB. */
void removeInROB() { robEntry = false; }
/** Sets this instruction as squashed in the ROB. */
void setSquashedInROB() { squashedInROB = true; }
/** Returns whether or not this instruction is squashed in the ROB. */
bool isSquashedInROB() const { return squashedInROB; }
void clearInROB() { status.reset(RobEntry); }
/** Returns whether or not this instruction is in the ROB. */
bool isInROB() const { return robEntry; }
bool isInROB() const { return status[RobEntry]; }
/** Sets this instruction as squashed in the ROB. */
void setSquashedInROB() { status.set(SquashedInROB); }
/** Returns whether or not this instruction is squashed in the ROB. */
bool isSquashedInROB() const { return status[SquashedInROB]; }
/** Read the PC of this instruction. */
const Addr readPC() const { return PC; }
@@ -590,17 +543,18 @@ class BaseDynInst : public FastAlloc, public RefCounted
void setNextPC(uint64_t val)
{
nextPC = val;
// instResult.integer = val;
}
/** Sets the ASID. */
void setASID(short addr_space_id) { asid = addr_space_id; }
void setThread(unsigned tid) { threadNumber = tid; }
/** Sets the thread id. */
void setTid(unsigned tid) { threadNumber = tid; }
void setState(ImplState *state) { thread = state; }
/** Sets the pointer to the thread state. */
void setThreadState(ImplState *state) { thread = state; }
/** Returns the thread context.
*/
/** Returns the thread context. */
ThreadContext *tcBase() { return thread->getTC(); }
private:
@@ -637,8 +591,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Store queue index. */
int16_t sqIdx;
bool reachedCommit;
/** Iterator pointing to this BaseDynInst in the list of all insts. */
ListIt instListIt;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,10 +41,6 @@
#include "mem/request.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_cpu.hh"
//#include "cpu/ozone/simple_impl.hh"
//#include "cpu/ozone/ozone_impl.hh"
using namespace std;
using namespace TheISA;
@@ -71,8 +67,8 @@ my_hash_t thishash;
template <class Impl>
BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC,
Addr pred_PC, InstSeqNum seq_num,
FullCPU *cpu)
: staticInst(machInst), traceData(NULL), cpu(cpu)/*, xc(cpu->xcBase())*/
ImplCPU *cpu)
: staticInst(machInst), traceData(NULL), cpu(cpu)
{
seqNum = seq_num;
@@ -99,37 +95,18 @@ BaseDynInst<Impl>::initVars()
memData = NULL;
effAddr = 0;
physEffAddr = 0;
storeSize = 0;
readyRegs = 0;
// May want to turn this into a bit vector or something.
completed = false;
resultReady = false;
canIssue = false;
issued = false;
executed = false;
canCommit = false;
committed = false;
squashed = false;
squashedInIQ = false;
squashedInLSQ = false;
squashedInROB = false;
instResult.integer = 0;
status.reset();
eaCalcDone = false;
memOpDone = false;
lqIdx = -1;
sqIdx = -1;
reachedCommit = false;
blockingInst = false;
recoverInst = false;
iqEntry = false;
robEntry = false;
serializeBefore = false;
serializeAfter = false;
serializeHandled = false;
// Eventually make this a parameter.
threadNumber = 0;
@@ -242,31 +219,7 @@ template <class Impl>
void
BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
{
// Need to create a MemReq here so we can do a translation. This
// will casue a TLB miss trap if necessary... not sure whether
// that's the best thing to do or not. We don't really need the
// MemReq otherwise, since wh64 has no functional effect.
/*
MemReqPtr req = new MemReq(addr, thread->getXCProxy(), size, flags);
req->asid = asid;
fault = cpu->translateDataWriteReq(req);
if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
// Record key MemReq parameters so we can generate another one
// just like it for the timing access without calling translate()
// again (which might mess up the TLB).
effAddr = req->vaddr;
physEffAddr = req->paddr;
memReqFlags = req->flags;
} else {
// ignore faults & accesses to uncacheable space... treat as no-op
effAddr = physEffAddr = MemReq::inval_addr;
}
storeSize = size;
storeData = 0;
*/
// Not currently supported.
}
/**
@@ -276,22 +229,7 @@ template <class Impl>
Fault
BaseDynInst<Impl>::copySrcTranslate(Addr src)
{
/*
MemReqPtr req = new MemReq(src, thread->getXCProxy(), 64);
req->asid = asid;
// translate to physical address
Fault fault = cpu->translateDataReadReq(req);
if (fault == NoFault) {
thread->copySrcAddr = src;
thread->copySrcPhysAddr = req->paddr;
} else {
thread->copySrcAddr = 0;
thread->copySrcPhysAddr = 0;
}
return fault;
*/
// Not currently supported.
return NoFault;
}
@@ -302,26 +240,7 @@ template <class Impl>
Fault
BaseDynInst<Impl>::copy(Addr dest)
{
/*
uint8_t data[64];
FunctionalMemory *mem = thread->mem;
assert(thread->copySrcPhysAddr);
MemReqPtr req = new MemReq(dest, thread->getXCProxy(), 64);
req->asid = asid;
// translate to physical address
Fault fault = cpu->translateDataWriteReq(req);
if (fault == NoFault) {
Addr dest_addr = req->paddr;
// Need to read straight from memory since we have more than 8 bytes.
req->paddr = thread->copySrcPhysAddr;
mem->read(req, data);
req->paddr = dest_addr;
mem->write(req, data);
}
return fault;
*/
// Not currently supported.
return NoFault;
}
@@ -350,7 +269,7 @@ void
BaseDynInst<Impl>::markSrcRegReady()
{
if (++readyRegs == numSrcRegs()) {
canIssue = true;
status.set(CanIssue);
}
}
@@ -358,13 +277,9 @@ template <class Impl>
void
BaseDynInst<Impl>::markSrcRegReady(RegIndex src_idx)
{
++readyRegs;
_readySrcRegIdx[src_idx] = true;
if (readyRegs == numSrcRegs()) {
canIssue = true;
}
markSrcRegReady();
}
template <class Impl>
@@ -382,25 +297,3 @@ BaseDynInst<Impl>::eaSrcsReady()
return true;
}
// Forward declaration
template class BaseDynInst<AlphaSimpleImpl>;
template <>
int
BaseDynInst<AlphaSimpleImpl>::instcount = 0;
/*
// Forward declaration
template class BaseDynInst<SimpleImpl>;
template <>
int
BaseDynInst<SimpleImpl>::instcount = 0;
// Forward declaration
template class BaseDynInst<OzoneImpl>;
template <>
int
BaseDynInst<OzoneImpl>::instcount = 0;
*/

View File

@@ -31,27 +31,17 @@
#include <list>
#include <string>
#include "base/refcnt.hh"
#include "cpu/base.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "cpu/static_inst.hh"
#include "mem/packet_impl.hh"
#include "sim/byteswap.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
//#include "cpu/ozone/dyn_inst.hh"
//#include "cpu/ozone/ozone_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
#if FULL_SYSTEM
#include "sim/system.hh"
#include "arch/vtophys.hh"
#include "kern/kernel_stats.hh"
#endif // FULL_SYSTEM
using namespace std;
@@ -77,6 +67,7 @@ CheckerCPU::CheckerCPU(Params *p)
changedPC = willChangePC = changedNextPC = false;
exitOnError = p->exitOnError;
warnOnlyOnLoadError = p->warnOnlyOnLoadError;
#if FULL_SYSTEM
itb = p->itb;
dtb = p->dtb;
@@ -84,6 +75,8 @@ CheckerCPU::CheckerCPU(Params *p)
#else
process = p->process;
#endif
result.integer = 0;
}
CheckerCPU::~CheckerCPU()
@@ -406,379 +399,10 @@ CheckerCPU::checkFlags(Request *req)
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
CheckerCPU::dumpAndExit()
{
DynInstPtr inst;
// Either check this instruction, or add it to a list of
// instructions waiting to be checked. Instructions must be
// checked in program order, so if a store has committed yet not
// completed, there may be some instructions that are waiting
// behind it that have completed and must be checked.
if (!instList.empty()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
if (!instList.front()->isCompleted()) {
return;
} else {
inst = instList.front();
instList.pop_front();
}
} else {
if (!completed_inst->isCompleted()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
return;
} else {
if (youngestSN < completed_inst->seqNum) {
inst = completed_inst;
youngestSN = completed_inst->seqNum;
} else {
return;
}
}
}
// Try to check all instructions that are completed, ending if we
// run out of instructions to check or if an instruction is not
// yet completed.
while (1) {
DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
inst->seqNum, inst->readPC());
unverifiedResult.integer = inst->readIntResult();
unverifiedReq = inst->req;
unverifiedMemData = inst->memData;
numCycles++;
Fault fault = NoFault;
// maintain $r0 semantics
thread->setIntReg(ZeroReg, 0);
#ifdef TARGET_ALPHA
thread->setFloatRegDouble(ZeroReg, 0.0);
#endif // TARGET_ALPHA
// Check if any recent PC changes match up with anything we
// expect to happen. This is mostly to check if traps or
// PC-based events have occurred in both the checker and CPU.
if (changedPC) {
DPRINTF(Checker, "Changed PC recently to %#x\n",
thread->readPC());
if (willChangePC) {
if (newPC == thread->readPC()) {
DPRINTF(Checker, "Changed PC matches expected PC\n");
} else {
warn("%lli: Changed PC does not match expected PC, "
"changed: %#x, expected: %#x",
curTick, thread->readPC(), newPC);
handleError();
}
willChangePC = false;
}
changedPC = false;
}
if (changedNextPC) {
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
thread->readNextPC());
changedNextPC = false;
}
// Try to fetch the instruction
#if FULL_SYSTEM
#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
#else
#define IFETCH_FLAGS(pc) 0
#endif
uint64_t fetch_PC = thread->readPC() & ~3;
// set up memory request for instruction fetch
memReq = new Request(inst->threadNumber, fetch_PC,
sizeof(uint32_t),
IFETCH_FLAGS(thread->readPC()),
fetch_PC, thread->readCpuId(), inst->threadNumber);
bool succeeded = translateInstReq(memReq);
if (!succeeded) {
if (inst->getFault() == NoFault) {
// In this case the instruction was not a dummy
// instruction carrying an ITB fault. In the single
// threaded case the ITB should still be able to
// translate this instruction; in the SMT case it's
// possible that its ITB entry was kicked out.
warn("%lli: Instruction PC %#x was not found in the ITB!",
curTick, thread->readPC());
handleError();
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
return;
} else {
// The instruction is carrying an ITB fault. Handle
// the fault and see if our results match the CPU on
// the next tick().
fault = inst->getFault();
}
}
if (fault == NoFault) {
Packet *pkt = new Packet(memReq, Packet::ReadReq,
Packet::Broadcast);
pkt->dataStatic(&machInst);
icachePort->sendFunctional(pkt);
delete pkt;
// keep an instruction count
numInst++;
// decode the instruction
machInst = gtoh(machInst);
// Checks that the instruction matches what we expected it to be.
// Checks both the machine instruction and the PC.
validateInst(inst);
curStaticInst = StaticInst::decode(makeExtMI(machInst,
thread->readPC()));
#if FULL_SYSTEM
thread->setInst(machInst);
#endif // FULL_SYSTEM
fault = inst->getFault();
}
// Discard fetch's memReq.
delete memReq;
memReq = NULL;
// Either the instruction was a fault and we should process the fault,
// or we should just go ahead execute the instruction. This assumes
// that the instruction is properly marked as a fault.
if (fault == NoFault) {
thread->funcExeInst++;
fault = curStaticInst->execute(this, NULL);
// Checks to make sure instrution results are correct.
validateExecution(inst);
if (curStaticInst->isLoad()) {
++numLoad;
}
}
if (fault != NoFault) {
#if FULL_SYSTEM
fault->invoke(tc);
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
#else // !FULL_SYSTEM
fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC());
#endif // FULL_SYSTEM
} else {
#if THE_ISA != MIPS_ISA
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
#else
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextNPC());
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
#endif
}
#if FULL_SYSTEM
// @todo: Determine if these should happen only if the
// instruction hasn't faulted. In the SimpleCPU case this may
// not be true, but in the O3 or Ozone case this may be true.
Addr oldpc;
int count = 0;
do {
oldpc = thread->readPC();
system->pcEventQueue.service(tc);
count++;
} while (oldpc != thread->readPC());
if (count > 1) {
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
}
#endif
// @todo: Optionally can check all registers. (Or just those
// that have been modified).
validateState();
if (memReq) {
delete memReq;
memReq = NULL;
}
// Continue verifying instructions if there's another completed
// instruction waiting to be verified.
if (instList.empty()) {
break;
} else if (instList.front()->isCompleted()) {
inst = instList.front();
instList.pop_front();
} else {
break;
}
}
warn("%lli: Checker PC:%#x, next PC:%#x",
curTick, thread->readPC(), thread->readNextPC());
panic("Checker found an error!");
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::switchOut(Sampler *s)
{
instList.clear();
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
{
if (inst->readPC() != thread->readPC()) {
warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
curTick, inst->readPC(), thread->readPC());
if (changedPC) {
warn("%lli: Changed PCs recently, may not be an error",
curTick);
} else {
handleError();
}
}
MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
if (mi != machInst) {
warn("%lli: Binary instructions do not match! Inst: %#x, "
"checker: %#x",
curTick, mi, machInst);
handleError();
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
{
if (inst->numDestRegs()) {
// @todo: Support more destination registers.
if (inst->isUnverifiable()) {
// Unverifiable instructions assume they were executed
// properly by the CPU. Grab the result from the
// instruction and write it to the register.
RegIndex idx = inst->destRegIdx(0);
if (idx < TheISA::FP_Base_DepTag) {
thread->setIntReg(idx, inst->readIntResult());
} else if (idx < TheISA::Fpcr_DepTag) {
thread->setFloatRegBits(idx, inst->readIntResult());
} else {
thread->setMiscReg(idx, inst->readIntResult());
}
} else if (result.integer != inst->readIntResult()) {
warn("%lli: Instruction results do not match! (Values may not "
"actually be integers) Inst: %#x, checker: %#x",
curTick, inst->readIntResult(), result.integer);
handleError();
}
}
if (inst->readNextPC() != thread->readNextPC()) {
warn("%lli: Instruction next PCs do not match! Inst: %#x, "
"checker: %#x",
curTick, inst->readNextPC(), thread->readNextPC());
handleError();
}
// Checking side effect registers can be difficult if they are not
// checked simultaneously with the execution of the instruction.
// This is because other valid instructions may have modified
// these registers in the meantime, and their values are not
// stored within the DynInst.
while (!miscRegIdxs.empty()) {
int misc_reg_idx = miscRegIdxs.front();
miscRegIdxs.pop();
if (inst->tcBase()->readMiscReg(misc_reg_idx) !=
thread->readMiscReg(misc_reg_idx)) {
warn("%lli: Misc reg idx %i (side effect) does not match! "
"Inst: %#x, checker: %#x",
curTick, misc_reg_idx,
inst->tcBase()->readMiscReg(misc_reg_idx),
thread->readMiscReg(misc_reg_idx));
handleError();
}
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateState()
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::dumpInsts()
{
int num = 0;
InstListIt inst_list_it = --(instList.end());
cprintf("Inst list size: %i\n", instList.size());
while (inst_list_it != instList.end())
{
cprintf("Instruction:%i\n",
num);
cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
(*inst_list_it)->readPC(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isCompleted());
cprintf("\n");
inst_list_it--;
++num;
}
}
//template
//class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
template
class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;

View File

@@ -66,7 +66,6 @@ class ThreadContext;
class MemInterface;
class Checkpoint;
class Request;
class Sampler;
/**
* CheckerCPU class. Dynamically verifies instructions as they are
@@ -103,6 +102,7 @@ class CheckerCPU : public BaseCPU
Process *process;
#endif
bool exitOnError;
bool warnOnlyOnLoadError;
};
public:
@@ -127,6 +127,12 @@ class CheckerCPU : public BaseCPU
Port *dcachePort;
virtual Port *getPort(const std::string &name, int idx)
{
panic("Not supported on checker!");
return NULL;
}
public:
// Primary thread being run.
SimpleThread *thread;
@@ -335,10 +341,13 @@ class CheckerCPU : public BaseCPU
void handleError()
{
if (exitOnError)
panic("Checker found error!");
dumpAndExit();
}
bool checkFlags(Request *req);
void dumpAndExit();
ThreadContext *tcBase() { return tc; }
SimpleThread *threadBase() { return thread; }
@@ -351,6 +360,7 @@ class CheckerCPU : public BaseCPU
uint64_t newPC;
bool changedNextPC;
bool exitOnError;
bool warnOnlyOnLoadError;
InstSeqNum youngestSN;
};
@@ -369,15 +379,26 @@ class Checker : public CheckerCPU
: CheckerCPU(p)
{ }
void switchOut(Sampler *s);
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
void tick(DynInstPtr &inst);
void verify(DynInstPtr &inst);
void validateInst(DynInstPtr &inst);
void validateExecution(DynInstPtr &inst);
void validateState();
void copyResult(DynInstPtr &inst);
private:
void handleError(DynInstPtr &inst)
{
if (exitOnError)
dumpAndExit(inst);
}
void dumpAndExit(DynInstPtr &inst);
std::list<DynInstPtr> instList;
typedef typename std::list<DynInstPtr>::iterator InstListIt;
void dumpInsts();

458
src/cpu/checker/cpu_impl.hh Normal file
View File

@@ -0,0 +1,458 @@
/*
* Copyright (c) 2006 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: Kevin Lim
*/
#include <list>
#include <string>
#include "base/refcnt.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "cpu/static_inst.hh"
#include "mem/packet_impl.hh"
#include "sim/byteswap.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#if FULL_SYSTEM
#include "arch/vtophys.hh"
#endif // FULL_SYSTEM
using namespace std;
//The CheckerCPU does alpha only
using namespace AlphaISA;
template <class DynInstPtr>
void
Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
{
DynInstPtr inst;
// Either check this instruction, or add it to a list of
// instructions waiting to be checked. Instructions must be
// checked in program order, so if a store has committed yet not
// completed, there may be some instructions that are waiting
// behind it that have completed and must be checked.
if (!instList.empty()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
if (!instList.front()->isCompleted()) {
return;
} else {
inst = instList.front();
instList.pop_front();
}
} else {
if (!completed_inst->isCompleted()) {
if (youngestSN < completed_inst->seqNum) {
DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
completed_inst->seqNum, completed_inst->readPC());
instList.push_back(completed_inst);
youngestSN = completed_inst->seqNum;
}
return;
} else {
if (youngestSN < completed_inst->seqNum) {
inst = completed_inst;
youngestSN = completed_inst->seqNum;
} else {
return;
}
}
}
// Try to check all instructions that are completed, ending if we
// run out of instructions to check or if an instruction is not
// yet completed.
while (1) {
DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
inst->seqNum, inst->readPC());
unverifiedResult.integer = inst->readIntResult();
unverifiedReq = inst->req;
unverifiedMemData = inst->memData;
numCycles++;
Fault fault = NoFault;
// maintain $r0 semantics
thread->setIntReg(ZeroReg, 0);
#ifdef TARGET_ALPHA
thread->setFloatRegDouble(ZeroReg, 0.0);
#endif // TARGET_ALPHA
// Check if any recent PC changes match up with anything we
// expect to happen. This is mostly to check if traps or
// PC-based events have occurred in both the checker and CPU.
if (changedPC) {
DPRINTF(Checker, "Changed PC recently to %#x\n",
thread->readPC());
if (willChangePC) {
if (newPC == thread->readPC()) {
DPRINTF(Checker, "Changed PC matches expected PC\n");
} else {
warn("%lli: Changed PC does not match expected PC, "
"changed: %#x, expected: %#x",
curTick, thread->readPC(), newPC);
CheckerCPU::handleError();
}
willChangePC = false;
}
changedPC = false;
}
if (changedNextPC) {
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
thread->readNextPC());
changedNextPC = false;
}
// Try to fetch the instruction
#if FULL_SYSTEM
#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
#else
#define IFETCH_FLAGS(pc) 0
#endif
uint64_t fetch_PC = thread->readPC() & ~3;
// set up memory request for instruction fetch
memReq = new Request(inst->threadNumber, fetch_PC,
sizeof(uint32_t),
IFETCH_FLAGS(thread->readPC()),
fetch_PC, thread->readCpuId(), inst->threadNumber);
bool succeeded = translateInstReq(memReq);
if (!succeeded) {
if (inst->getFault() == NoFault) {
// In this case the instruction was not a dummy
// instruction carrying an ITB fault. In the single
// threaded case the ITB should still be able to
// translate this instruction; in the SMT case it's
// possible that its ITB entry was kicked out.
warn("%lli: Instruction PC %#x was not found in the ITB!",
curTick, thread->readPC());
handleError(inst);
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
return;
} else {
// The instruction is carrying an ITB fault. Handle
// the fault and see if our results match the CPU on
// the next tick().
fault = inst->getFault();
}
}
if (fault == NoFault) {
Packet *pkt = new Packet(memReq, Packet::ReadReq,
Packet::Broadcast);
pkt->dataStatic(&machInst);
icachePort->sendFunctional(pkt);
delete pkt;
// keep an instruction count
numInst++;
// decode the instruction
machInst = gtoh(machInst);
// Checks that the instruction matches what we expected it to be.
// Checks both the machine instruction and the PC.
validateInst(inst);
curStaticInst = StaticInst::decode(makeExtMI(machInst,
thread->readPC()));
#if FULL_SYSTEM
thread->setInst(machInst);
#endif // FULL_SYSTEM
fault = inst->getFault();
}
// Discard fetch's memReq.
delete memReq;
memReq = NULL;
// Either the instruction was a fault and we should process the fault,
// or we should just go ahead execute the instruction. This assumes
// that the instruction is properly marked as a fault.
if (fault == NoFault) {
thread->funcExeInst++;
fault = curStaticInst->execute(this, NULL);
// Checks to make sure instrution results are correct.
validateExecution(inst);
if (curStaticInst->isLoad()) {
++numLoad;
}
}
if (fault != NoFault) {
#if FULL_SYSTEM
fault->invoke(tc);
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
#endif
} else {
#if THE_ISA != MIPS_ISA
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
#else
// go to the next instruction
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->readNextNPC());
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
#endif
}
#if FULL_SYSTEM
// @todo: Determine if these should happen only if the
// instruction hasn't faulted. In the SimpleCPU case this may
// not be true, but in the O3 or Ozone case this may be true.
Addr oldpc;
int count = 0;
do {
oldpc = thread->readPC();
system->pcEventQueue.service(tc);
count++;
} while (oldpc != thread->readPC());
if (count > 1) {
willChangePC = true;
newPC = thread->readPC();
DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
}
#endif
// @todo: Optionally can check all registers. (Or just those
// that have been modified).
validateState();
if (memReq) {
delete memReq;
memReq = NULL;
}
// Continue verifying instructions if there's another completed
// instruction waiting to be verified.
if (instList.empty()) {
break;
} else if (instList.front()->isCompleted()) {
inst = instList.front();
instList.pop_front();
} else {
break;
}
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::switchOut()
{
instList.clear();
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
{
if (inst->readPC() != thread->readPC()) {
warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
curTick, inst->readPC(), thread->readPC());
if (changedPC) {
warn("%lli: Changed PCs recently, may not be an error",
curTick);
} else {
handleError(inst);
}
}
MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
if (mi != machInst) {
warn("%lli: Binary instructions do not match! Inst: %#x, "
"checker: %#x",
curTick, mi, machInst);
handleError(inst);
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
{
bool result_mismatch = false;
if (inst->numDestRegs()) {
// @todo: Support more destination registers.
if (inst->isUnverifiable()) {
// Unverifiable instructions assume they were executed
// properly by the CPU. Grab the result from the
// instruction and write it to the register.
copyResult(inst);
} else if (result.integer != inst->readIntResult()) {
result_mismatch = true;
}
}
if (result_mismatch) {
warn("%lli: Instruction results do not match! (Values may not "
"actually be integers) Inst: %#x, checker: %#x",
curTick, inst->readIntResult(), result.integer);
// It's useful to verify load values from memory, but in MP
// systems the value obtained at execute may be different than
// the value obtained at completion. Similarly DMA can
// present the same problem on even UP systems. Thus there is
// the option to only warn on loads having a result error.
if (inst->isLoad() && warnOnlyOnLoadError) {
copyResult(inst);
} else {
handleError(inst);
}
}
if (inst->readNextPC() != thread->readNextPC()) {
warn("%lli: Instruction next PCs do not match! Inst: %#x, "
"checker: %#x",
curTick, inst->readNextPC(), thread->readNextPC());
handleError(inst);
}
// Checking side effect registers can be difficult if they are not
// checked simultaneously with the execution of the instruction.
// This is because other valid instructions may have modified
// these registers in the meantime, and their values are not
// stored within the DynInst.
while (!miscRegIdxs.empty()) {
int misc_reg_idx = miscRegIdxs.front();
miscRegIdxs.pop();
if (inst->tcBase()->readMiscReg(misc_reg_idx) !=
thread->readMiscReg(misc_reg_idx)) {
warn("%lli: Misc reg idx %i (side effect) does not match! "
"Inst: %#x, checker: %#x",
curTick, misc_reg_idx,
inst->tcBase()->readMiscReg(misc_reg_idx),
thread->readMiscReg(misc_reg_idx));
handleError(inst);
}
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateState()
{
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::copyResult(DynInstPtr &inst)
{
RegIndex idx = inst->destRegIdx(0);
if (idx < TheISA::FP_Base_DepTag) {
thread->setIntReg(idx, inst->readIntResult());
} else if (idx < TheISA::Fpcr_DepTag) {
thread->setFloatRegBits(idx, inst->readIntResult());
} else {
thread->setMiscReg(idx, inst->readIntResult());
}
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
{
cprintf("Error detected, instruction information:\n");
cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
inst->readPC(),
inst->readNextPC(),
inst->seqNum,
inst->threadNumber,
inst->isCompleted());
inst->dump();
CheckerCPU::dumpAndExit();
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::dumpInsts()
{
int num = 0;
InstListIt inst_list_it = --(instList.end());
cprintf("Inst list size: %i\n", instList.size());
while (inst_list_it != instList.end())
{
cprintf("Instruction:%i\n",
num);
cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
"Completed:%i\n",
(*inst_list_it)->readPC(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isCompleted());
cprintf("\n");
inst_list_it--;
++num;
}
}

View File

@@ -120,7 +120,7 @@ class CheckerThreadContext : public ThreadContext
void suspend() { actualTC->suspend(); }
/// Set the status to Unallocated.
void deallocate() { actualTC->deallocate(); }
void deallocate(int delay = 0) { actualTC->deallocate(delay); }
/// Set the status to Halted.
void halt() { actualTC->halt(); }

View File

@@ -26,6 +26,10 @@
#
# Authors: Steve Reinhardt
import os
import os.path
import sys
################
# CpuModel class
#
@@ -47,7 +51,6 @@ class CpuModel:
# Add self to dict
CpuModel.dict[name] = self
#
# Define CPU models.
#
@@ -67,9 +70,6 @@ CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc',
CpuModel('FullCPU', 'full_cpu_exec.cc',
'#include "encumbered/cpu/full/dyn_inst.hh"',
{ 'CPU_exec_context': 'DynInst' })
CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc',
'#include "cpu/o3/alpha_dyn_inst.hh"',
{ 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc',
'#include "cpu/ozone/dyn_inst.hh"',
{ 'CPU_exec_context': 'OzoneDynInst<SimpleImpl>' })
@@ -79,4 +79,6 @@ CpuModel('OzoneCPU', 'ozone_exec.cc',
CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
'#include "cpu/checker/cpu.hh"',
{ 'CPU_exec_context': 'CheckerCPU' })
CpuModel('O3CPU', 'o3_cpu_exec.cc',
'#include "cpu/o3/isa_specific.hh"',
{ 'CPU_exec_context': 'O3DynInst' })

View File

@@ -36,7 +36,7 @@
class ThreadContext;
/** This class creates a global list of events than need a pointer to an
/** This class creates a global list of events that need a pointer to a
* thread context. When a switchover takes place the events can be migrated
* to the new thread context, otherwise you could have a wake timer interrupt
* go off on a switched out cpu or other unfortunate events. This object MUST be

161
src/cpu/exec_context.hh Normal file
View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2002-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: Kevin Lim
*/
#error "Cannot include this file"
/**
* The ExecContext is not a usable class. It is simply here for
* documentation purposes. It shows the interface that is used by the
* ISA to access and change CPU state.
*/
class ExecContext {
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to reduce overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
/** Reads an integer register. */
uint64_t readIntReg(const StaticInst *si, int idx);
/** Reads a floating point register of a specific width. */
FloatReg readFloatReg(const StaticInst *si, int idx, int width);
/** Reads a floating point register of single register width. */
FloatReg readFloatReg(const StaticInst *si, int idx);
/** Reads a floating point register of a specific width in its
* binary format, instead of by value. */
FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width);
/** Reads a floating point register in its binary format, instead
* of by value. */
FloatRegBits readFloatRegBits(const StaticInst *si, int idx);
/** Sets an integer register to a value. */
void setIntReg(const StaticInst *si, int idx, uint64_t val);
/** Sets a floating point register of a specific width to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width);
/** Sets a floating point register of single width to a value. */
void setFloatReg(const StaticInst *si, int idx, FloatReg val);
/** Sets the bits of a floating point register of a specific width
* to a binary value. */
void setFloatRegBits(const StaticInst *si, int idx,
FloatRegBits val, int width);
/** Sets the bits of a floating point register of single width
* to a binary value. */
void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val);
/** Reads the PC. */
uint64_t readPC();
/** Reads the NextPC. */
uint64_t readNextPC();
/** Reads the Next-NextPC. Only for architectures like SPARC or MIPS. */
uint64_t readNextNPC();
/** Sets the PC. */
void setPC(uint64_t val);
/** Sets the NextPC. */
void setNextPC(uint64_t val);
/** Sets the Next-NextPC. Only for architectures like SPARC or MIPS. */
void setNextNPC(uint64_t val);
/** Reads a miscellaneous register. */
MiscReg readMiscReg(int misc_reg);
/** Reads a miscellaneous register, handling any architectural
* side effects due to reading that register. */
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
/** Sets a miscellaneous register. */
Fault setMiscReg(int misc_reg, const MiscReg &val);
/** Sets a miscellaneous register, handling any architectural
* side effects due to writing that register. */
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
/** Records the effective address of the instruction. Only valid
* for memory ops. */
void setEA(Addr EA);
/** Returns the effective address of the instruction. Only valid
* for memory ops. */
Addr getEA();
/** Returns a pointer to the ThreadContext. */
ThreadContext *tcBase();
/** Reads an address, creating a memory request with the given
* flags. Stores result of read in data. */
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
/** Writes to an address, creating a memory request with the given
* flags. Writes data to memory. For store conditionals, returns
* the result of the store in res. */
template <class T>
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
/** Prefetches an address, creating a memory request with the
* given flags. */
void prefetch(Addr addr, unsigned flags);
/** Hints to the memory system that an address will be written to
* soon, with the given size. Creates a memory request with the
* given flags. */
void writeHint(Addr addr, int size, unsigned flags);
#if FULL_SYSTEM
/** Somewhat Alpha-specific function that handles returning from
* an error or interrupt. */
Fault hwrei();
/** Reads the interrupt flags. */
int readIntrFlag();
/** Sets the interrupt flags to a value. */
void setIntrFlag(int val);
/**
* Check for special simulator handling of specific PAL calls. If
* return value is false, actual PAL call will be suppressed.
*/
bool simPalCheck(int palFunc);
#else
/** Executes a syscall specified by the callnum. */
void syscall(int64_t callnum);
#endif
};

171
src/cpu/func_unit.cc Normal file
View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2002-2006 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: Steve Raasch
*/
#include <sstream>
#include "base/misc.hh"
#include "cpu/func_unit.hh"
#include "sim/builder.hh"
using namespace std;
////////////////////////////////////////////////////////////////////////////
//
// The funciton unit
//
FuncUnit::FuncUnit()
{
capabilityList.reset();
}
// Copy constructor
FuncUnit::FuncUnit(const FuncUnit &fu)
{
for (int i = 0; i < Num_OpClasses; ++i) {
opLatencies[i] = fu.opLatencies[i];
issueLatencies[i] = fu.issueLatencies[i];
}
capabilityList = fu.capabilityList;
}
void
FuncUnit::addCapability(OpClass cap, unsigned oplat, unsigned issuelat)
{
if (issuelat == 0 || oplat == 0)
panic("FuncUnit: you don't really want a zero-cycle latency do you?");
capabilityList.set(cap);
opLatencies[cap] = oplat;
issueLatencies[cap] = issuelat;
}
bool
FuncUnit::provides(OpClass capability)
{
return capabilityList[capability];
}
bitset<Num_OpClasses>
FuncUnit::capabilities()
{
return capabilityList;
}
unsigned &
FuncUnit::opLatency(OpClass cap)
{
return opLatencies[cap];
}
unsigned
FuncUnit::issueLatency(OpClass capability)
{
return issueLatencies[capability];
}
////////////////////////////////////////////////////////////////////////////
//
// The SimObjects we use to get the FU information into the simulator
//
////////////////////////////////////////////////////////////////////////////
//
// We use 2 objects to specify this data in the INI file:
// (1) OpDesc - Describes the operation class & latencies
// (multiple OpDesc objects can refer to the same
// operation classes)
// (2) FUDesc - Describes the operations available in the unit &
// the number of these units
//
//
//
// The operation-class description object
//
BEGIN_DECLARE_SIM_OBJECT_PARAMS(OpDesc)
SimpleEnumParam<OpClass> opClass;
Param<unsigned> opLat;
Param<unsigned> issueLat;
END_DECLARE_SIM_OBJECT_PARAMS(OpDesc)
BEGIN_INIT_SIM_OBJECT_PARAMS(OpDesc)
INIT_ENUM_PARAM(opClass, "type of operation", opClassStrings),
INIT_PARAM(opLat, "cycles until result is available"),
INIT_PARAM(issueLat, "cycles until another can be issued")
END_INIT_SIM_OBJECT_PARAMS(OpDesc)
CREATE_SIM_OBJECT(OpDesc)
{
return new OpDesc(getInstanceName(), opClass, opLat, issueLat);
}
REGISTER_SIM_OBJECT("OpDesc", OpDesc)
//
// The FuDesc object
//
BEGIN_DECLARE_SIM_OBJECT_PARAMS(FUDesc)
SimObjectVectorParam<OpDesc *> opList;
Param<unsigned> count;
END_DECLARE_SIM_OBJECT_PARAMS(FUDesc)
BEGIN_INIT_SIM_OBJECT_PARAMS(FUDesc)
INIT_PARAM(opList, "list of operation classes for this FU type"),
INIT_PARAM(count, "number of these FU's available")
END_INIT_SIM_OBJECT_PARAMS(FUDesc)
CREATE_SIM_OBJECT(FUDesc)
{
return new FUDesc(getInstanceName(), opList, count);
}
REGISTER_SIM_OBJECT("FUDesc", FUDesc)

101
src/cpu/func_unit.hh Normal file
View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2002-2006 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: Steve Raasch
*/
#ifndef __CPU_FUNC_UNIT_HH__
#define __CPU_FUNC_UNIT_HH__
#include <bitset>
#include <string>
#include <vector>
#include "cpu/op_class.hh"
#include "sim/sim_object.hh"
////////////////////////////////////////////////////////////////////////////
//
// Structures used ONLY during the initialization phase...
//
//
//
struct OpDesc : public SimObject
{
OpClass opClass;
unsigned opLat;
unsigned issueLat;
OpDesc(std::string name, OpClass c, unsigned o, unsigned i)
: SimObject(name), opClass(c), opLat(o), issueLat(i) {};
};
struct FUDesc : public SimObject
{
std::vector<OpDesc *> opDescList;
unsigned number;
FUDesc(std::string name, std::vector<OpDesc *> l, unsigned n)
: SimObject(name), opDescList(l), number(n) {};
};
typedef std::vector<OpDesc *>::iterator OPDDiterator;
typedef std::vector<FUDesc *>::iterator FUDDiterator;
////////////////////////////////////////////////////////////////////////////
//
// The actual FU object
//
//
//
class FuncUnit
{
private:
unsigned opLatencies[Num_OpClasses];
unsigned issueLatencies[Num_OpClasses];
std::bitset<Num_OpClasses> capabilityList;
public:
FuncUnit();
FuncUnit(const FuncUnit &fu);
std::string name;
void addCapability(OpClass cap, unsigned oplat, unsigned issuelat);
bool provides(OpClass capability);
std::bitset<Num_OpClasses> capabilities();
unsigned &opLatency(OpClass capability);
unsigned issueLatency(OpClass capability);
};
#endif // __FU_POOL_HH__

79
src/cpu/o3/SConscript Executable file
View File

@@ -0,0 +1,79 @@
# -*- mode:python -*-
# Copyright (c) 2006 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: Korey Sewell
import os
import os.path
import sys
# Import build environment variable from SConstruct.
Import('env')
#################################################################
#
# Include ISA-specific files for the O3 CPU-model
#
#################################################################
sources = []
if env['TARGET_ISA'] == 'alpha':
sources += Split('''
alpha/dyn_inst.cc
alpha/cpu.cc
alpha/thread_context.cc
alpha/cpu_builder.cc
''')
elif env['TARGET_ISA'] == 'mips':
sys.exit('O3 CPU does not support MIPS')
#sources += Split('''
# mips/dyn_inst.cc
# mips/cpu.cc
# mips/thread_context.cc
# mips/cpu_builder.cc
# ''')
elif env['TARGET_ISA'] == 'sparc':
sys.exit('O3 CPU does not support MIPS')
#sources += Split('''
# sparc/dyn_inst.cc
# sparc/cpu.cc
# sparc/thread_context.cc
# sparc/cpu_builder.cc
# ''')
else:
sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA'])
# Convert file names to SCons File objects. This takes care of the
# path relative to the top of the directory tree.
sources = [File(s) for s in sources]
Return('sources')

View File

@@ -28,11 +28,11 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_cpu_impl.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/alpha/cpu_impl.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
// Force instantiation of AlphaFullCPU for all the implemntations that are
// Force instantiation of AlphaO3CPU for all the implemntations that are
// needed. Consider merging this and alpha_dyn_inst.cc, and maybe all
// classes that depend on a certain impl, into one file (alpha_impl.cc?).
template class AlphaFullCPU<AlphaSimpleImpl>;
template class AlphaO3CPU<AlphaSimpleImpl>;

204
src/cpu/o3/alpha/cpu.hh Normal file
View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
*/
#ifndef __CPU_O3_ALPHA_CPU_HH__
#define __CPU_O3_ALPHA_CPU_HH__
#include "arch/isa_traits.hh"
#include "cpu/thread_context.hh"
#include "cpu/o3/cpu.hh"
#include "sim/byteswap.hh"
class EndQuiesceEvent;
namespace Kernel {
class Statistics;
};
class TranslatingPort;
/**
* AlphaO3CPU class. Derives from the FullO3CPU class, and
* implements all ISA and implementation specific functions of the
* CPU. This is the CPU class that is used for the SimObjects, and is
* what is given to the DynInsts. Most of its state exists in the
* FullO3CPU; the state is has is mainly for ISA specific
* functionality.
*/
template <class Impl>
class AlphaO3CPU : public FullO3CPU<Impl>
{
protected:
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
typedef TheISA::RegFile RegFile;
typedef TheISA::MiscRegFile MiscRegFile;
public:
typedef O3ThreadState<Impl> ImplState;
typedef O3ThreadState<Impl> Thread;
typedef typename Impl::Params Params;
/** Constructs an AlphaO3CPU with the given parameters. */
AlphaO3CPU(Params *params);
#if FULL_SYSTEM
/** ITB pointer. */
AlphaITB *itb;
/** DTB pointer. */
AlphaDTB *dtb;
#endif
/** Registers statistics. */
void regStats();
#if FULL_SYSTEM
/** Translates instruction requestion. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return itb->translate(req, thread->getTC());
}
/** Translates data read request. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), false);
}
/** Translates data write request. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), true);
}
#else
/** Translates instruction requestion in syscall emulation mode. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data read request in syscall emulation mode. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data write request in syscall emulation mode. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
#endif
/** Reads a miscellaneous register. */
MiscReg readMiscReg(int misc_reg, unsigned tid);
/** Reads a misc. register, including any side effects the read
* might have as defined by the architecture.
*/
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
/** Sets a miscellaneous register. */
Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
/** Sets a misc. register, including any side effects the write
* might have as defined by the architecture.
*/
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
/** Initiates a squash of all in-flight instructions for a given
* thread. The source of the squash is an external update of
* state through the TC.
*/
void squashFromTC(unsigned tid);
#if FULL_SYSTEM
/** Posts an interrupt. */
void post_interrupt(int int_num, int index);
/** Reads the interrupt flag. */
int readIntrFlag();
/** Sets the interrupt flags. */
void setIntrFlag(int val);
/** HW return from error interrupt. */
Fault hwrei(unsigned tid);
/** Returns if a specific PC is a PAL mode PC. */
bool inPalMode(uint64_t PC)
{ return AlphaISA::PcPAL(PC); }
bool simPalCheck(int palFunc, unsigned tid);
/** Processes any interrupts. */
void processInterrupts();
/** Halts the CPU. */
void halt() { panic("Halt not implemented!\n"); }
#endif
/** Traps to handle given fault. */
void trap(Fault fault, unsigned tid);
#if !FULL_SYSTEM
/** Executes a syscall.
* @todo: Determine if this needs to be virtual.
*/
void syscall(int64_t callnum, int tid);
/** Gets a syscall argument. */
IntReg getSyscallArg(int i, int tid);
/** Used to shift args for indirect syscall. */
void setSyscallArg(int i, IntReg val, int tid);
/** Sets the return value of a syscall. */
void setSyscallReturn(SyscallReturn return_value, int tid);
#endif
/** CPU read function, forwards read to LSQ. */
template <class T>
Fault read(RequestPtr &req, T &data, int load_idx)
{
return this->iew.ldstQueue.read(req, data, load_idx);
}
/** CPU write function, forwards write to LSQ. */
template <class T>
Fault write(RequestPtr &req, T &data, int store_idx)
{
return this->iew.ldstQueue.write(req, data, store_idx);
}
Addr lockAddr;
/** Temporary fix for the lock flag, works in the UP case. */
bool lockFlag;
};
#endif // __CPU_O3_ALPHA_CPU_HH__

View File

@@ -31,21 +31,21 @@
#include <string>
#include "cpu/base.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_params.hh"
#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/fu_pool.hh"
#include "sim/builder.hh"
class DerivAlphaFullCPU : public AlphaFullCPU<AlphaSimpleImpl>
class DerivO3CPU : public AlphaO3CPU<AlphaSimpleImpl>
{
public:
DerivAlphaFullCPU(AlphaSimpleParams *p)
: AlphaFullCPU<AlphaSimpleImpl>(p)
DerivO3CPU(AlphaSimpleParams *p)
: AlphaO3CPU<AlphaSimpleImpl>(p)
{ }
};
BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
Param<int> clock;
Param<int> numThreads;
@@ -91,12 +91,10 @@ Param<unsigned> renameWidth;
Param<unsigned> commitToIEWDelay;
Param<unsigned> renameToIEWDelay;
Param<unsigned> issueToExecuteDelay;
Param<unsigned> dispatchWidth;
Param<unsigned> issueWidth;
Param<unsigned> executeWidth;
Param<unsigned> executeIntWidth;
Param<unsigned> executeFloatWidth;
Param<unsigned> executeBranchWidth;
Param<unsigned> executeMemoryWidth;
Param<unsigned> wbWidth;
Param<unsigned> wbDepth;
SimObjectParam<FUPool *> fuPool;
Param<unsigned> iewToCommitDelay;
@@ -104,7 +102,9 @@ Param<unsigned> renameToROBDelay;
Param<unsigned> commitWidth;
Param<unsigned> squashWidth;
Param<Tick> trapLatency;
Param<Tick> fetchTrapLatency;
Param<unsigned> backComSize;
Param<unsigned> forwardComSize;
Param<std::string> predType;
Param<unsigned> localPredictorSize;
@@ -149,9 +149,9 @@ Param<bool> defer_registration;
Param<bool> function_trace;
Param<Tick> function_trace_start;
END_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
END_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
INIT_PARAM(clock, "clock speed"),
INIT_PARAM(numThreads, "number of HW thread contexts"),
@@ -212,12 +212,10 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
"Issue/Execute/Writeback delay"),
INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
"to the IEW stage)"),
INIT_PARAM(dispatchWidth, "Dispatch width"),
INIT_PARAM(issueWidth, "Issue width"),
INIT_PARAM(executeWidth, "Execute width"),
INIT_PARAM(executeIntWidth, "Integer execute width"),
INIT_PARAM(executeFloatWidth, "Floating point execute width"),
INIT_PARAM(executeBranchWidth, "Branch execute width"),
INIT_PARAM(executeMemoryWidth, "Memory execute width"),
INIT_PARAM(wbWidth, "Writeback width"),
INIT_PARAM(wbDepth, "Writeback depth (number of cycles it can buffer)"),
INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
@@ -226,7 +224,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
INIT_PARAM(commitWidth, "Commit width"),
INIT_PARAM(squashWidth, "Squash width"),
INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6),
INIT_PARAM_DFLT(fetchTrapLatency, "Number of cycles before the fetch trap is handled", 12),
INIT_PARAM(backComSize, "Time buffer size for backwards communication"),
INIT_PARAM(forwardComSize, "Time buffer size for forward communication"),
INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
INIT_PARAM(localPredictorSize, "Size of local predictor"),
@@ -271,11 +271,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
INIT_PARAM(function_trace, "Enable function trace"),
INIT_PARAM(function_trace_start, "Cycle to start function trace")
END_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
END_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
CREATE_SIM_OBJECT(DerivAlphaFullCPU)
CREATE_SIM_OBJECT(DerivO3CPU)
{
DerivAlphaFullCPU *cpu;
DerivO3CPU *cpu;
#if FULL_SYSTEM
// Full-system only supports a single thread for the moment.
@@ -284,12 +284,12 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
// In non-full-system mode, we infer the number of threads from
// the workload if it's not explicitly specified.
int actual_num_threads =
numThreads.isValid() ? numThreads : workload.size();
(numThreads.isValid() && numThreads >= workload.size()) ?
numThreads : workload.size();
if (workload.size() == 0) {
fatal("Must specify at least one workload!");
}
#endif
AlphaSimpleParams *params = new AlphaSimpleParams;
@@ -343,12 +343,10 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->commitToIEWDelay = commitToIEWDelay;
params->renameToIEWDelay = renameToIEWDelay;
params->issueToExecuteDelay = issueToExecuteDelay;
params->dispatchWidth = dispatchWidth;
params->issueWidth = issueWidth;
params->executeWidth = executeWidth;
params->executeIntWidth = executeIntWidth;
params->executeFloatWidth = executeFloatWidth;
params->executeBranchWidth = executeBranchWidth;
params->executeMemoryWidth = executeMemoryWidth;
params->wbWidth = wbWidth;
params->wbDepth = wbDepth;
params->fuPool = fuPool;
params->iewToCommitDelay = iewToCommitDelay;
@@ -356,7 +354,9 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->commitWidth = commitWidth;
params->squashWidth = squashWidth;
params->trapLatency = trapLatency;
params->fetchTrapLatency = fetchTrapLatency;
params->backComSize = backComSize;
params->forwardComSize = forwardComSize;
params->predType = predType;
params->localPredictorSize = localPredictorSize;
@@ -386,7 +386,16 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->numROBEntries = numROBEntries;
params->smtNumFetchingThreads = smtNumFetchingThreads;
params->smtFetchPolicy = smtFetchPolicy;
// Default smtFetchPolicy to "RoundRobin", if necessary.
std::string round_robin_policy = "RoundRobin";
std::string single_thread = "SingleThread";
if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0)
params->smtFetchPolicy = round_robin_policy;
else
params->smtFetchPolicy = smtFetchPolicy;
params->smtIQPolicy = smtIQPolicy;
params->smtLSQPolicy = smtLSQPolicy;
params->smtLSQThreshold = smtLSQThreshold;
@@ -401,10 +410,10 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;
cpu = new DerivAlphaFullCPU(params);
cpu = new DerivO3CPU(params);
return cpu;
}
REGISTER_SIM_OBJECT("DerivAlphaFullCPU", DerivAlphaFullCPU)
REGISTER_SIM_OBJECT("DerivO3CPU", DerivO3CPU)

View File

@@ -0,0 +1,422 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
*/
#include "config/use_checker.hh"
#include "arch/alpha/faults.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/checker/thread_context.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/alpha/thread_context.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/thread_state.hh"
#if FULL_SYSTEM
#include "arch/alpha/osfpal.hh"
#include "arch/isa_traits.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
#endif
using namespace TheISA;
template <class Impl>
AlphaO3CPU<Impl>::AlphaO3CPU(Params *params)
#if FULL_SYSTEM
: FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
#else
: FullO3CPU<Impl>(params)
#endif
{
DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n");
// Setup any thread state.
this->thread.resize(this->numThreads);
for (int i = 0; i < this->numThreads; ++i) {
#if FULL_SYSTEM
// SMT is not supported in FS mode yet.
assert(this->numThreads == 1);
this->thread[i] = new Thread(this, 0);
this->thread[i]->setStatus(ThreadContext::Suspended);
#else
if (i < params->workload.size()) {
DPRINTF(O3CPU, "Workload[%i] process is %#x",
i, this->thread[i]);
this->thread[i] = new Thread(this, i, params->workload[i],
i, params->mem);
this->thread[i]->setStatus(ThreadContext::Suspended);
#if !FULL_SYSTEM
/* Use this port to for syscall emulation writes to memory. */
Port *mem_port;
TranslatingPort *trans_port;
trans_port = new TranslatingPort(csprintf("%s-%d-funcport",
name(), i),
params->workload[i]->pTable,
false);
mem_port = params->mem->getPort("functional");
mem_port->setPeer(trans_port);
trans_port->setPeer(mem_port);
this->thread[i]->setMemPort(trans_port);
#endif
//usedTids[i] = true;
//threadMap[i] = i;
} else {
//Allocate Empty thread so M5 can use later
//when scheduling threads to CPU
Process* dummy_proc = NULL;
this->thread[i] = new Thread(this, i, dummy_proc, i, params->mem);
//usedTids[i] = false;
}
#endif // !FULL_SYSTEM
ThreadContext *tc;
// Setup the TC that will serve as the interface to the threads/CPU.
AlphaTC<Impl> *alpha_tc =
new AlphaTC<Impl>;
tc = alpha_tc;
// If we're using a checker, then the TC should be the
// CheckerThreadContext.
#if USE_CHECKER
if (params->checker) {
tc = new CheckerThreadContext<AlphaTC<Impl> >(
alpha_tc, this->checker);
}
#endif
alpha_tc->cpu = this;
alpha_tc->thread = this->thread[i];
#if FULL_SYSTEM
// Setup quiesce event.
this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
Port *mem_port;
FunctionalPort *phys_port;
VirtualPort *virt_port;
phys_port = new FunctionalPort(csprintf("%s-%d-funcport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(phys_port);
phys_port->setPeer(mem_port);
virt_port = new VirtualPort(csprintf("%s-%d-vport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(virt_port);
virt_port->setPeer(mem_port);
this->thread[i]->setPhysPort(phys_port);
this->thread[i]->setVirtPort(virt_port);
#endif
// Give the thread the TC.
this->thread[i]->tc = tc;
// Add the TC to the CPU's list of TC's.
this->threadContexts.push_back(tc);
}
for (int i=0; i < this->numThreads; i++) {
this->thread[i]->setFuncExeInst(0);
}
// Sets CPU pointers. These must be set at this level because the CPU
// pointers are defined to be the highest level of CPU class.
this->fetch.setCPU(this);
this->decode.setCPU(this);
this->rename.setCPU(this);
this->iew.setCPU(this);
this->commit.setCPU(this);
this->rob.setCPU(this);
this->regFile.setCPU(this);
lockAddr = 0;
lockFlag = false;
}
template <class Impl>
void
AlphaO3CPU<Impl>::regStats()
{
// Register stats for everything that has stats.
this->fullCPURegStats();
this->fetch.regStats();
this->decode.regStats();
this->rename.regStats();
this->iew.regStats();
this->commit.regStats();
}
template <class Impl>
MiscReg
AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
{
return this->regFile.readMiscReg(misc_reg, tid);
}
template <class Impl>
MiscReg
AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
unsigned tid)
{
return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
}
template <class Impl>
Fault
AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
{
return this->regFile.setMiscReg(misc_reg, val, tid);
}
template <class Impl>
Fault
AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
unsigned tid)
{
return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
}
template <class Impl>
void
AlphaO3CPU<Impl>::squashFromTC(unsigned tid)
{
this->thread[tid]->inSyscall = true;
this->commit.generateTCEvent(tid);
}
#if FULL_SYSTEM
template <class Impl>
void
AlphaO3CPU<Impl>::post_interrupt(int int_num, int index)
{
BaseCPU::post_interrupt(int_num, index);
if (this->thread[0]->status() == ThreadContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
this->threadContexts[0]->activate();
}
}
template <class Impl>
int
AlphaO3CPU<Impl>::readIntrFlag()
{
return this->regFile.readIntrFlag();
}
template <class Impl>
void
AlphaO3CPU<Impl>::setIntrFlag(int val)
{
this->regFile.setIntrFlag(val);
}
template <class Impl>
Fault
AlphaO3CPU<Impl>::hwrei(unsigned tid)
{
// Need to clear the lock flag upon returning from an interrupt.
this->lockFlag = false;
this->thread[tid]->kernelStats->hwrei();
this->checkInterrupts = true;
// FIXME: XXX check for interrupts? XXX
return NoFault;
}
template <class Impl>
bool
AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
{
if (this->thread[tid]->kernelStats)
this->thread[tid]->kernelStats->callpal(palFunc,
this->threadContexts[tid]);
switch (palFunc) {
case PAL::halt:
halt();
if (--System::numSystemsRunning == 0)
exitSimLoop("all cpus halted");
break;
case PAL::bpt:
case PAL::bugchk:
if (this->system->breakpoint())
return false;
break;
}
return true;
}
template <class Impl>
void
AlphaO3CPU<Impl>::processInterrupts()
{
// Check for interrupts here. For now can copy the code that
// exists within isa_fullsys_traits.hh. Also assume that thread 0
// is the one that handles the interrupts.
// @todo: Possibly consolidate the interrupt checking code.
// @todo: Allow other threads to handle interrupts.
// Check if there are any outstanding interrupts
//Handle the interrupts
int ipl = 0;
int summary = 0;
this->checkInterrupts = false;
if (this->readMiscReg(IPR_ASTRR, 0))
panic("asynchronous traps not implemented\n");
if (this->readMiscReg(IPR_SIRR, 0)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
}
}
uint64_t interrupts = this->intr_status();
if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = i;
summary |= (ULL(1) << i);
}
}
}
if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
this->setMiscReg(IPR_ISR, summary, 0);
this->setMiscReg(IPR_INTID, ipl, 0);
// Checker needs to know these two registers were updated.
#if USE_CHECKER
if (this->checker) {
this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
}
#endif
this->trap(Fault(new InterruptFault), 0);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
this->readMiscReg(IPR_IPLR, 0), ipl, summary);
}
}
#endif // FULL_SYSTEM
template <class Impl>
void
AlphaO3CPU<Impl>::trap(Fault fault, unsigned tid)
{
// Pass the thread's TC into the invoke method.
fault->invoke(this->threadContexts[tid]);
}
#if !FULL_SYSTEM
template <class Impl>
void
AlphaO3CPU<Impl>::syscall(int64_t callnum, int tid)
{
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
DPRINTF(Activity,"Activity: syscall() called.\n");
// Temporarily increase this by one to account for the syscall
// instruction.
++(this->thread[tid]->funcExeInst);
// Execute the actual syscall.
this->thread[tid]->syscall(callnum);
// Decrease funcExeInst by one as the normal commit will handle
// incrementing it.
--(this->thread[tid]->funcExeInst);
}
template <class Impl>
TheISA::IntReg
AlphaO3CPU<Impl>::getSyscallArg(int i, int tid)
{
return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
}
template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
{
this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
}
template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
{
// 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
this->setArchIntReg(SyscallSuccessReg, 0, tid);
this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
} else {
// got an error, return details
this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
}
}
#endif

View File

@@ -28,8 +28,8 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst_impl.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha/dyn_inst_impl.hh"
#include "cpu/o3/alpha/impl.hh"
// Force instantiation of AlphaDynInst for all the implementations that
// are needed.

View File

@@ -34,8 +34,8 @@
#include "arch/isa_traits.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/impl.hh"
class Packet;
@@ -51,7 +51,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
{
public:
/** Typedef for the CPU. */
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
/** Binary machine instruction type. */
typedef TheISA::MachInst MachInst;
@@ -74,7 +74,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
public:
/** BaseDynInst constructor given a binary instruction. */
AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
FullCPU *cpu);
O3CPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
AlphaDynInst(StaticInstPtr &_staticInst);

View File

@@ -28,11 +28,11 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
InstSeqNum seq_num, FullCPU *cpu)
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
{
initVars();
@@ -102,15 +102,7 @@ template <class Impl>
Fault
AlphaDynInst<Impl>::completeAcc(Packet *pkt)
{
if (this->isLoad()) {
this->fault = this->staticInst->completeAcc(pkt, this,
this->traceData);
} else if (this->isStore()) {
this->fault = this->staticInst->completeAcc(pkt, this,
this->traceData);
} else {
panic("Unknown type!");
}
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
return this->fault;
}

View File

@@ -33,20 +33,21 @@
#include "arch/alpha/isa_traits.hh"
#include "cpu/o3/alpha_params.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/cpu_policy.hh"
// Forward declarations.
template <class Impl>
class AlphaDynInst;
template <class Impl>
class AlphaFullCPU;
class AlphaO3CPU;
/** Implementation specific struct that defines several key types to the
* CPU, the stages within the CPU, the time buffers, and the DynInst.
* The struct defines the ISA, the CPU policy, the specific DynInst, the
* specific FullCPU, and all of the structs from the time buffers to do
* specific O3CPU, and all of the structs from the time buffers to do
* communication.
* This is one of the key things that must be defined for each hardware
* specific CPU implementation.
@@ -67,8 +68,14 @@ struct AlphaSimpleImpl
*/
typedef RefCountingPtr<DynInst> DynInstPtr;
/** The FullCPU type to be used. */
typedef AlphaFullCPU<AlphaSimpleImpl> FullCPU;
/** The O3CPU type to be used. */
typedef AlphaO3CPU<AlphaSimpleImpl> O3CPU;
/** Same typedef, but for CPUType. BaseDynInst may not always use
* an O3 CPU, so it's clearer to call it CPUType instead in that
* case.
*/
typedef O3CPU CPUType;
/** The Params to be passed to each stage. */
typedef AlphaSimpleParams Params;
@@ -79,4 +86,7 @@ struct AlphaSimpleImpl
};
};
/** The O3Impl to be used. */
typedef AlphaSimpleImpl O3CPUImpl;
#endif // __CPU_O3_ALPHA_IMPL_HH__

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
*/
#ifndef __CPU_O3_ALPHA_PARAMS_HH__
#define __CPU_O3_ALPHA_PARAMS_HH__
#include "cpu/o3/cpu.hh"
#include "cpu/o3/params.hh"
//Forward declarations
class AlphaDTB;
class AlphaITB;
class MemObject;
class Process;
class System;
/**
* This file defines the parameters that will be used for the AlphaO3CPU.
* This must be defined externally so that the Impl can have a params class
* defined that it can pass to all of the individual stages.
*/
class AlphaSimpleParams : public O3Params
{
public:
#if FULL_SYSTEM
AlphaITB *itb;
AlphaDTB *dtb;
#endif
};
#endif // __CPU_O3_ALPHA_PARAMS_HH__

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
* Korey Sewell
*/
#include "cpu/o3/thread_context.hh"
#include "cpu/o3/thread_context_impl.hh"
template class O3ThreadContext<AlphaSimpleImpl>;

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
* Korey Sewell
*/
#include "cpu/o3/thread_context.hh"
template <class Impl>
class AlphaTC : public O3ThreadContext<Impl>
{
public:
#if FULL_SYSTEM
/** Returns a pointer to the ITB. */
virtual AlphaITB *getITBPtr() { return this->cpu->itb; }
/** Returns a pointer to the DTB. */
virtual AlphaDTB *getDTBPtr() { return this->cpu->dtb; }
/** Returns pointer to the quiesce event. */
virtual EndQuiesceEvent *getQuiesceEvent()
{
return this->thread->quiesceEvent;
}
/** Returns if the thread is currently in PAL mode, based on
* the PC's value. */
virtual bool inPalMode()
{ return TheISA::PcPAL(this->cpu->readPC(this->thread->readTid())); }
#endif
virtual uint64_t readNextNPC()
{
panic("Alpha has no NextNPC!");
return 0;
}
virtual void setNextNPC(uint64_t val)
{
panic("Alpha has no NextNPC!");
}
virtual void changeRegFileContext(TheISA::RegFile::ContextParam param,
TheISA::RegFile::ContextVal val)
{ panic("Not supported on Alpha!"); }
/** This function exits the thread context in the CPU and returns
* 1 if the CPU has no more active threads (meaning it's OK to exit);
* Used in syscall-emulation mode when a thread executes the 'exit'
* syscall.
*/
virtual int exit()
{
this->deallocate();
// If there are still threads executing in the system
if (this->cpu->numActiveThreads())
return 0; // don't exit simulation
else
return 1; // exit simulation
}
};

View File

@@ -1,434 +0,0 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
*/
#ifndef __CPU_O3_ALPHA_FULL_CPU_HH__
#define __CPU_O3_ALPHA_FULL_CPU_HH__
#include "arch/isa_traits.hh"
#include "cpu/thread_context.hh"
#include "cpu/o3/cpu.hh"
#include "sim/byteswap.hh"
class EndQuiesceEvent;
namespace Kernel {
class Statistics;
};
class TranslatingPort;
/**
* AlphaFullCPU class. Derives from the FullO3CPU class, and
* implements all ISA and implementation specific functions of the
* CPU. This is the CPU class that is used for the SimObjects, and is
* what is given to the DynInsts. Most of its state exists in the
* FullO3CPU; the state is has is mainly for ISA specific
* functionality.
*/
template <class Impl>
class AlphaFullCPU : public FullO3CPU<Impl>
{
protected:
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
typedef TheISA::RegFile RegFile;
typedef TheISA::MiscRegFile MiscRegFile;
public:
typedef O3ThreadState<Impl> ImplState;
typedef O3ThreadState<Impl> Thread;
typedef typename Impl::Params Params;
/** Constructs an AlphaFullCPU with the given parameters. */
AlphaFullCPU(Params *params);
/**
* Derived ThreadContext class for use with the AlphaFullCPU. It
* provides the interface for any external objects to access a
* single thread's state and some general CPU state. Any time
* external objects try to update state through this interface,
* the CPU will create an event to squash all in-flight
* instructions in order to ensure state is maintained correctly.
* It must be defined specifically for the AlphaFullCPU because
* not all architectural state is located within the O3ThreadState
* (such as the commit PC, and registers), and specific actions
* must be taken when using this interface (such as squashing all
* in-flight instructions when doing a write to this interface).
*/
class AlphaTC : public ThreadContext
{
public:
/** Pointer to the CPU. */
AlphaFullCPU<Impl> *cpu;
/** Pointer to the thread state that this TC corrseponds to. */
O3ThreadState<Impl> *thread;
/** Returns a pointer to this CPU. */
virtual BaseCPU *getCpuPtr() { return cpu; }
/** Sets this CPU's ID. */
virtual void setCpuId(int id) { cpu->cpu_id = id; }
/** Reads this CPU's ID. */
virtual int readCpuId() { return cpu->cpu_id; }
#if FULL_SYSTEM
/** Returns a pointer to the system. */
virtual System *getSystemPtr() { return cpu->system; }
/** Returns a pointer to physical memory. */
virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
/** Returns a pointer to the ITB. */
virtual AlphaITB *getITBPtr() { return cpu->itb; }
/** Returns a pointer to the DTB. */
virtual AlphaDTB *getDTBPtr() { return cpu->dtb; }
/** Returns a pointer to this thread's kernel statistics. */
virtual Kernel::Statistics *getKernelStats()
{ return thread->kernelStats; }
virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); }
virtual VirtualPort *getVirtPort(ThreadContext *src_tc = NULL);
void delVirtPort(VirtualPort *vp);
#else
virtual TranslatingPort *getMemPort() { return thread->getMemPort(); }
/** Returns a pointer to this thread's process. */
virtual Process *getProcessPtr() { return thread->getProcessPtr(); }
#endif
/** Returns this thread's status. */
virtual Status status() const { return thread->status(); }
/** Sets this thread's status. */
virtual void setStatus(Status new_status)
{ thread->setStatus(new_status); }
/** Set the status to Active. Optional delay indicates number of
* cycles to wait before beginning execution. */
virtual void activate(int delay = 1);
/** Set the status to Suspended. */
virtual void suspend();
/** Set the status to Unallocated. */
virtual void deallocate();
/** Set the status to Halted. */
virtual void halt();
#if FULL_SYSTEM
/** Dumps the function profiling information.
* @todo: Implement.
*/
virtual void dumpFuncProfile();
#endif
/** Takes over execution of a thread from another CPU. */
virtual void takeOverFrom(ThreadContext *old_context);
/** Registers statistics associated with this TC. */
virtual void regStats(const std::string &name);
/** Serializes state. */
virtual void serialize(std::ostream &os);
/** Unserializes state. */
virtual void unserialize(Checkpoint *cp, const std::string &section);
#if FULL_SYSTEM
/** Returns pointer to the quiesce event. */
virtual EndQuiesceEvent *getQuiesceEvent();
/** Reads the last tick that this thread was activated on. */
virtual Tick readLastActivate();
/** Reads the last tick that this thread was suspended on. */
virtual Tick readLastSuspend();
/** Clears the function profiling information. */
virtual void profileClear();
/** Samples the function profiling information. */
virtual void profileSample();
#endif
/** Returns this thread's ID number. */
virtual int getThreadNum() { return thread->readTid(); }
/** Returns the instruction this thread is currently committing.
* Only used when an instruction faults.
*/
virtual TheISA::MachInst getInst();
/** Copies the architectural registers from another TC into this TC. */
virtual void copyArchRegs(ThreadContext *tc);
/** Resets all architectural registers to 0. */
virtual void clearArchRegs();
/** Reads an integer register. */
virtual uint64_t readIntReg(int reg_idx);
virtual FloatReg readFloatReg(int reg_idx, int width);
virtual FloatReg readFloatReg(int reg_idx);
virtual FloatRegBits readFloatRegBits(int reg_idx, int width);
virtual FloatRegBits readFloatRegBits(int reg_idx);
/** Sets an integer register to a value. */
virtual void setIntReg(int reg_idx, uint64_t val);
virtual void setFloatReg(int reg_idx, FloatReg val, int width);
virtual void setFloatReg(int reg_idx, FloatReg val);
virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
virtual void setFloatRegBits(int reg_idx, FloatRegBits val);
/** Reads this thread's PC. */
virtual uint64_t readPC()
{ return cpu->readPC(thread->readTid()); }
/** Sets this thread's PC. */
virtual void setPC(uint64_t val);
/** Reads this thread's next PC. */
virtual uint64_t readNextPC()
{ return cpu->readNextPC(thread->readTid()); }
/** Sets this thread's next PC. */
virtual void setNextPC(uint64_t val);
virtual uint64_t readNextNPC()
{
panic("Alpha has no NextNPC!");
return 0;
}
virtual void setNextNPC(uint64_t val)
{ }
/** Reads a miscellaneous register. */
virtual MiscReg readMiscReg(int misc_reg)
{ return cpu->readMiscReg(misc_reg, thread->readTid()); }
/** Reads a misc. register, including any side-effects the
* read might have as defined by the architecture. */
virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
{ return cpu->readMiscRegWithEffect(misc_reg, fault, thread->readTid()); }
/** Sets a misc. register. */
virtual Fault setMiscReg(int misc_reg, const MiscReg &val);
/** Sets a misc. register, including any side-effects the
* write might have as defined by the architecture. */
virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
/** Returns the number of consecutive store conditional failures. */
// @todo: Figure out where these store cond failures should go.
virtual unsigned readStCondFailures()
{ return thread->storeCondFailures; }
/** Sets the number of consecutive store conditional failures. */
virtual void setStCondFailures(unsigned sc_failures)
{ thread->storeCondFailures = sc_failures; }
#if FULL_SYSTEM
/** Returns if the thread is currently in PAL mode, based on
* the PC's value. */
virtual bool inPalMode()
{ return TheISA::PcPAL(cpu->readPC(thread->readTid())); }
#endif
// Only really makes sense for old CPU model. Lots of code
// outside the CPU still checks this function, so it will
// always return false to keep everything working.
/** Checks if the thread is misspeculating. Because it is
* very difficult to determine if the thread is
* misspeculating, this is set as false. */
virtual bool misspeculating() { return false; }
#if !FULL_SYSTEM
/** Gets a syscall argument by index. */
virtual IntReg getSyscallArg(int i);
/** Sets a syscall argument. */
virtual void setSyscallArg(int i, IntReg val);
/** Sets the syscall return value. */
virtual void setSyscallReturn(SyscallReturn return_value);
/** Executes a syscall in SE mode. */
virtual void syscall(int64_t callnum)
{ return cpu->syscall(callnum, thread->readTid()); }
/** Reads the funcExeInst counter. */
virtual Counter readFuncExeInst() { return thread->funcExeInst; }
#endif
virtual void changeRegFileContext(TheISA::RegFile::ContextParam param,
TheISA::RegFile::ContextVal val)
{ panic("Not supported on Alpha!"); }
};
#if FULL_SYSTEM
/** ITB pointer. */
AlphaITB *itb;
/** DTB pointer. */
AlphaDTB *dtb;
#endif
/** Registers statistics. */
void regStats();
#if FULL_SYSTEM
/** Translates instruction requestion. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return itb->translate(req, thread->getTC());
}
/** Translates data read request. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), false);
}
/** Translates data write request. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return dtb->translate(req, thread->getTC(), true);
}
#else
/** Translates instruction requestion in syscall emulation mode. */
Fault translateInstReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data read request in syscall emulation mode. */
Fault translateDataReadReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data write request in syscall emulation mode. */
Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
{
return thread->getProcessPtr()->pTable->translate(req);
}
#endif
/** Reads a miscellaneous register. */
MiscReg readMiscReg(int misc_reg, unsigned tid);
/** Reads a misc. register, including any side effects the read
* might have as defined by the architecture.
*/
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
/** Sets a miscellaneous register. */
Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
/** Sets a misc. register, including any side effects the write
* might have as defined by the architecture.
*/
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
/** Initiates a squash of all in-flight instructions for a given
* thread. The source of the squash is an external update of
* state through the TC.
*/
void squashFromTC(unsigned tid);
#if FULL_SYSTEM
/** Posts an interrupt. */
void post_interrupt(int int_num, int index);
/** Reads the interrupt flag. */
int readIntrFlag();
/** Sets the interrupt flags. */
void setIntrFlag(int val);
/** HW return from error interrupt. */
Fault hwrei(unsigned tid);
/** Returns if a specific PC is a PAL mode PC. */
bool inPalMode(uint64_t PC)
{ return AlphaISA::PcPAL(PC); }
/** Traps to handle given fault. */
void trap(Fault fault, unsigned tid);
bool simPalCheck(int palFunc, unsigned tid);
/** Processes any interrupts. */
void processInterrupts();
/** Halts the CPU. */
void halt() { panic("Halt not implemented!\n"); }
#endif
#if !FULL_SYSTEM
/** Executes a syscall.
* @todo: Determine if this needs to be virtual.
*/
void syscall(int64_t callnum, int tid);
/** Gets a syscall argument. */
IntReg getSyscallArg(int i, int tid);
/** Used to shift args for indirect syscall. */
void setSyscallArg(int i, IntReg val, int tid);
/** Sets the return value of a syscall. */
void setSyscallReturn(SyscallReturn return_value, int tid);
#endif
/** CPU read function, forwards read to LSQ. */
template <class T>
Fault read(RequestPtr &req, T &data, int load_idx)
{
return this->iew.ldstQueue.read(req, data, load_idx);
}
/** CPU write function, forwards write to LSQ. */
template <class T>
Fault write(RequestPtr &req, T &data, int store_idx)
{
return this->iew.ldstQueue.write(req, data, store_idx);
}
Addr lockAddr;
/** Temporary fix for the lock flag, works in the UP case. */
bool lockFlag;
};
#endif // __CPU_O3_ALPHA_FULL_CPU_HH__

View File

@@ -1,872 +0,0 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
*/
#include "arch/alpha/faults.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/checker/thread_context.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_params.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/thread_state.hh"
#if FULL_SYSTEM
#include "arch/alpha/osfpal.hh"
#include "arch/isa_traits.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
#include "sim/system.hh"
#endif
using namespace TheISA;
template <class Impl>
AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
#if FULL_SYSTEM
: FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
#else
: FullO3CPU<Impl>(params)
#endif
{
DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
// Setup any thread state.
this->thread.resize(this->numThreads);
for (int i = 0; i < this->numThreads; ++i) {
#if FULL_SYSTEM
// SMT is not supported in FS mode yet.
assert(this->numThreads == 1);
this->thread[i] = new Thread(this, 0);
this->thread[i]->setStatus(ThreadContext::Suspended);
#else
if (i < params->workload.size()) {
DPRINTF(FullCPU, "FullCPU: Workload[%i] process is %#x",
i, this->thread[i]);
this->thread[i] = new Thread(this, i, params->workload[i],
i, params->mem);
this->thread[i]->setStatus(ThreadContext::Suspended);
#if !FULL_SYSTEM
/* Use this port to for syscall emulation writes to memory. */
Port *mem_port;
TranslatingPort *trans_port;
trans_port = new TranslatingPort(csprintf("%s-%d-funcport",
name(), i),
params->workload[i]->pTable,
false);
mem_port = params->mem->getPort("functional");
mem_port->setPeer(trans_port);
trans_port->setPeer(mem_port);
this->thread[i]->setMemPort(trans_port);
#endif
//usedTids[i] = true;
//threadMap[i] = i;
} else {
//Allocate Empty thread so M5 can use later
//when scheduling threads to CPU
Process* dummy_proc = NULL;
this->thread[i] = new Thread(this, i, dummy_proc, i, params->mem);
//usedTids[i] = false;
}
#endif // !FULL_SYSTEM
ThreadContext *tc;
// Setup the TC that will serve as the interface to the threads/CPU.
AlphaTC *alpha_tc = new AlphaTC;
// If we're using a checker, then the TC should be the
// CheckerThreadContext.
if (params->checker) {
tc = new CheckerThreadContext<AlphaTC>(
alpha_tc, this->checker);
} else {
tc = alpha_tc;
}
alpha_tc->cpu = this;
alpha_tc->thread = this->thread[i];
#if FULL_SYSTEM
// Setup quiesce event.
this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
Port *mem_port;
FunctionalPort *phys_port;
VirtualPort *virt_port;
phys_port = new FunctionalPort(csprintf("%s-%d-funcport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(phys_port);
phys_port->setPeer(mem_port);
virt_port = new VirtualPort(csprintf("%s-%d-vport",
name(), i));
mem_port = this->system->physmem->getPort("functional");
mem_port->setPeer(virt_port);
virt_port->setPeer(mem_port);
this->thread[i]->setPhysPort(phys_port);
this->thread[i]->setVirtPort(virt_port);
#endif
// Give the thread the TC.
this->thread[i]->tc = tc;
// Add the TC to the CPU's list of TC's.
this->threadContexts.push_back(tc);
}
for (int i=0; i < this->numThreads; i++) {
this->thread[i]->setFuncExeInst(0);
}
// Sets CPU pointers. These must be set at this level because the CPU
// pointers are defined to be the highest level of CPU class.
this->fetch.setCPU(this);
this->decode.setCPU(this);
this->rename.setCPU(this);
this->iew.setCPU(this);
this->commit.setCPU(this);
this->rob.setCPU(this);
this->regFile.setCPU(this);
lockAddr = 0;
lockFlag = false;
}
template <class Impl>
void
AlphaFullCPU<Impl>::regStats()
{
// Register stats for everything that has stats.
this->fullCPURegStats();
this->fetch.regStats();
this->decode.regStats();
this->rename.regStats();
this->iew.regStats();
this->commit.regStats();
}
#if FULL_SYSTEM
template <class Impl>
VirtualPort *
AlphaFullCPU<Impl>::AlphaTC::getVirtPort(ThreadContext *src_tc)
{
if (!src_tc)
return thread->getVirtPort();
VirtualPort *vp;
Port *mem_port;
vp = new VirtualPort("tc-vport", src_tc);
mem_port = cpu->system->physmem->getPort("functional");
mem_port->setPeer(vp);
vp->setPeer(mem_port);
return vp;
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::dumpFuncProfile()
{
// Currently not supported
}
#endif
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::takeOverFrom(ThreadContext *old_context)
{
// some things should already be set up
#if FULL_SYSTEM
assert(getSystemPtr() == old_context->getSystemPtr());
#else
assert(getProcessPtr() == old_context->getProcessPtr());
#endif
// copy over functional state
setStatus(old_context->status());
copyArchRegs(old_context);
setCpuId(old_context->readCpuId());
#if !FULL_SYSTEM
thread->funcExeInst = old_context->readFuncExeInst();
#else
EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
if (other_quiesce) {
// Point the quiesce event's TC at this TC so that it wakes up
// the proper CPU.
other_quiesce->tc = this;
}
if (thread->quiesceEvent) {
thread->quiesceEvent->tc = this;
}
// Transfer kernel stats from one CPU to the other.
thread->kernelStats = old_context->getKernelStats();
// storeCondFailures = 0;
cpu->lockFlag = false;
#endif
old_context->setStatus(ThreadContext::Unallocated);
thread->inSyscall = false;
thread->trapPending = false;
}
#if FULL_SYSTEM
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::delVirtPort(VirtualPort *vp)
{
delete vp->getPeer();
delete vp;
}
#endif
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::activate(int delay)
{
DPRINTF(FullCPU, "Calling activate on AlphaTC\n");
if (thread->status() == ThreadContext::Active)
return;
#if FULL_SYSTEM
thread->lastActivate = curTick;
#endif
if (thread->status() == ThreadContext::Unallocated) {
cpu->activateWhenReady(thread->readTid());
return;
}
thread->setStatus(ThreadContext::Active);
// status() == Suspended
cpu->activateContext(thread->readTid(), delay);
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::suspend()
{
DPRINTF(FullCPU, "Calling suspend on AlphaTC\n");
if (thread->status() == ThreadContext::Suspended)
return;
#if FULL_SYSTEM
thread->lastActivate = curTick;
thread->lastSuspend = curTick;
#endif
/*
#if FULL_SYSTEM
// Don't change the status from active if there are pending interrupts
if (cpu->check_interrupts()) {
assert(status() == ThreadContext::Active);
return;
}
#endif
*/
thread->setStatus(ThreadContext::Suspended);
cpu->suspendContext(thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::deallocate()
{
DPRINTF(FullCPU, "Calling deallocate on AlphaTC\n");
if (thread->status() == ThreadContext::Unallocated)
return;
thread->setStatus(ThreadContext::Unallocated);
cpu->deallocateContext(thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::halt()
{
DPRINTF(FullCPU, "Calling halt on AlphaTC\n");
if (thread->status() == ThreadContext::Halted)
return;
thread->setStatus(ThreadContext::Halted);
cpu->haltContext(thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::regStats(const std::string &name)
{
#if FULL_SYSTEM
thread->kernelStats = new Kernel::Statistics(cpu->system);
thread->kernelStats->regStats(name + ".kern");
#endif
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::serialize(std::ostream &os)
{
#if FULL_SYSTEM
if (thread->kernelStats)
thread->kernelStats->serialize(os);
#endif
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::unserialize(Checkpoint *cp, const std::string &section)
{
#if FULL_SYSTEM
if (thread->kernelStats)
thread->kernelStats->unserialize(cp, section);
#endif
}
#if FULL_SYSTEM
template <class Impl>
EndQuiesceEvent *
AlphaFullCPU<Impl>::AlphaTC::getQuiesceEvent()
{
return thread->quiesceEvent;
}
template <class Impl>
Tick
AlphaFullCPU<Impl>::AlphaTC::readLastActivate()
{
return thread->lastActivate;
}
template <class Impl>
Tick
AlphaFullCPU<Impl>::AlphaTC::readLastSuspend()
{
return thread->lastSuspend;
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::profileClear()
{}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::profileSample()
{}
#endif
template <class Impl>
TheISA::MachInst
AlphaFullCPU<Impl>::AlphaTC:: getInst()
{
return thread->getInst();
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::copyArchRegs(ThreadContext *tc)
{
// This function will mess things up unless the ROB is empty and
// there are no instructions in the pipeline.
unsigned tid = thread->readTid();
PhysRegIndex renamed_reg;
// First loop through the integer registers.
for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
renamed_reg = cpu->renameMap[tid].lookup(i);
DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
"now has data %lli.\n",
renamed_reg, cpu->readIntReg(renamed_reg),
tc->readIntReg(i));
cpu->setIntReg(renamed_reg, tc->readIntReg(i));
}
// Then loop through the floating point registers.
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
cpu->setFloatRegBits(renamed_reg,
tc->readFloatRegBits(i));
}
// Copy the misc regs.
copyMiscRegs(tc, this);
// Then finally set the PC and the next PC.
cpu->setPC(tc->readPC(), tid);
cpu->setNextPC(tc->readNextPC(), tid);
#if !FULL_SYSTEM
this->thread->funcExeInst = tc->readFuncExeInst();
#endif
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::clearArchRegs()
{}
template <class Impl>
uint64_t
AlphaFullCPU<Impl>::AlphaTC::readIntReg(int reg_idx)
{
return cpu->readArchIntReg(reg_idx, thread->readTid());
}
template <class Impl>
FloatReg
AlphaFullCPU<Impl>::AlphaTC::readFloatReg(int reg_idx, int width)
{
switch(width) {
case 32:
return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
case 64:
return cpu->readArchFloatRegDouble(reg_idx, thread->readTid());
default:
panic("Unsupported width!");
return 0;
}
}
template <class Impl>
FloatReg
AlphaFullCPU<Impl>::AlphaTC::readFloatReg(int reg_idx)
{
return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
}
template <class Impl>
FloatRegBits
AlphaFullCPU<Impl>::AlphaTC::readFloatRegBits(int reg_idx, int width)
{
DPRINTF(Fault, "Reading floatint register through the TC!\n");
return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
}
template <class Impl>
FloatRegBits
AlphaFullCPU<Impl>::AlphaTC::readFloatRegBits(int reg_idx)
{
return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setIntReg(int reg_idx, uint64_t val)
{
cpu->setArchIntReg(reg_idx, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatReg(int reg_idx, FloatReg val, int width)
{
switch(width) {
case 32:
cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());
break;
case 64:
cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid());
break;
}
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatReg(int reg_idx, FloatReg val)
{
cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val,
int width)
{
DPRINTF(Fault, "Setting floatint register through the TC!\n");
cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val)
{
cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setPC(uint64_t val)
{
cpu->setPC(val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setNextPC(uint64_t val)
{
cpu->setNextPC(val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::AlphaTC::setMiscReg(int misc_reg, const MiscReg &val)
{
Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
return ret_fault;
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::AlphaTC::setMiscRegWithEffect(int misc_reg,
const MiscReg &val)
{
Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val,
thread->readTid());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromTC(thread->readTid());
}
return ret_fault;
}
#if !FULL_SYSTEM
template <class Impl>
TheISA::IntReg
AlphaFullCPU<Impl>::AlphaTC::getSyscallArg(int i)
{
return cpu->getSyscallArg(i, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setSyscallArg(int i, IntReg val)
{
cpu->setSyscallArg(i, val, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setSyscallReturn(SyscallReturn return_value)
{
cpu->setSyscallReturn(return_value, thread->readTid());
}
#endif // FULL_SYSTEM
template <class Impl>
MiscReg
AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
{
return this->regFile.readMiscReg(misc_reg, tid);
}
template <class Impl>
MiscReg
AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
unsigned tid)
{
return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
{
return this->regFile.setMiscReg(misc_reg, val, tid);
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
unsigned tid)
{
return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
}
template <class Impl>
void
AlphaFullCPU<Impl>::squashFromTC(unsigned tid)
{
this->thread[tid]->inSyscall = true;
this->commit.generateTCEvent(tid);
}
#if FULL_SYSTEM
template <class Impl>
void
AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
{
BaseCPU::post_interrupt(int_num, index);
if (this->thread[0]->status() == ThreadContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
this->threadContexts[0]->activate();
}
}
template <class Impl>
int
AlphaFullCPU<Impl>::readIntrFlag()
{
return this->regFile.readIntrFlag();
}
template <class Impl>
void
AlphaFullCPU<Impl>::setIntrFlag(int val)
{
this->regFile.setIntrFlag(val);
}
template <class Impl>
Fault
AlphaFullCPU<Impl>::hwrei(unsigned tid)
{
// Need to clear the lock flag upon returning from an interrupt.
this->lockFlag = false;
this->thread[tid]->kernelStats->hwrei();
this->checkInterrupts = true;
// FIXME: XXX check for interrupts? XXX
return NoFault;
}
template <class Impl>
bool
AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
{
if (this->thread[tid]->kernelStats)
this->thread[tid]->kernelStats->callpal(palFunc,
this->threadContexts[tid]);
switch (palFunc) {
case PAL::halt:
halt();
if (--System::numSystemsRunning == 0)
exitSimLoop("all cpus halted");
break;
case PAL::bpt:
case PAL::bugchk:
if (this->system->breakpoint())
return false;
break;
}
return true;
}
template <class Impl>
void
AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
{
// Pass the thread's TC into the invoke method.
fault->invoke(this->threadContexts[tid]);
}
template <class Impl>
void
AlphaFullCPU<Impl>::processInterrupts()
{
// Check for interrupts here. For now can copy the code that
// exists within isa_fullsys_traits.hh. Also assume that thread 0
// is the one that handles the interrupts.
// @todo: Possibly consolidate the interrupt checking code.
// @todo: Allow other threads to handle interrupts.
// Check if there are any outstanding interrupts
//Handle the interrupts
int ipl = 0;
int summary = 0;
this->checkInterrupts = false;
if (this->readMiscReg(IPR_ASTRR, 0))
panic("asynchronous traps not implemented\n");
if (this->readMiscReg(IPR_SIRR, 0)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
}
}
uint64_t interrupts = this->intr_status();
if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = i;
summary |= (ULL(1) << i);
}
}
}
if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
this->setMiscReg(IPR_ISR, summary, 0);
this->setMiscReg(IPR_INTID, ipl, 0);
// Checker needs to know these two registers were updated.
if (this->checker) {
this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
}
this->trap(Fault(new InterruptFault), 0);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
this->readMiscReg(IPR_IPLR, 0), ipl, summary);
}
}
#endif // FULL_SYSTEM
#if !FULL_SYSTEM
template <class Impl>
void
AlphaFullCPU<Impl>::syscall(int64_t callnum, int tid)
{
DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
DPRINTF(Activity,"Activity: syscall() called.\n");
// Temporarily increase this by one to account for the syscall
// instruction.
++(this->thread[tid]->funcExeInst);
// Execute the actual syscall.
this->thread[tid]->syscall(callnum);
// Decrease funcExeInst by one as the normal commit will handle
// incrementing it.
--(this->thread[tid]->funcExeInst);
}
template <class Impl>
TheISA::IntReg
AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
{
return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
}
template <class Impl>
void
AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
{
this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
}
template <class Impl>
void
AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
{
// 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
this->setArchIntReg(SyscallSuccessReg, 0, tid);
this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
} else {
// got an error, return details
this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
}
}
#endif

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2006 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: Kevin Lim
*/
#include "cpu/base_dyn_inst_impl.hh"
#include "cpu/o3/isa_specific.hh"
// Explicit instantiation
template class BaseDynInst<O3CPUImpl>;
template <>
int
BaseDynInst<O3CPUImpl>::instcount = 0;

View File

@@ -29,11 +29,6 @@
*/
#include "cpu/o3/bpred_unit_impl.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/ozone/ozone_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
#include "cpu/o3/isa_specific.hh"
template class BPredUnit<AlphaSimpleImpl>;
template class BPredUnit<OzoneImpl>;
//template class BPredUnit<SimpleImpl>;
template class BPredUnit<O3CPUImpl>;

View File

@@ -30,16 +30,19 @@
#include <string>
#include "cpu/checker/cpu.hh"
#include "cpu/checker/cpu_impl.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
#include "cpu/o3/alpha/impl.hh"
#include "sim/builder.hh"
#include "sim/process.hh"
#include "sim/sim_object.hh"
class MemObject;
template
class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
/**
* Specific non-templated derived class used for SimObject configuration.
*/
@@ -75,6 +78,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
Param<bool> defer_registration;
Param<bool> exitOnError;
Param<bool> warnOnlyOnLoadError;
Param<bool> function_trace;
Param<Tick> function_trace_start;
@@ -105,6 +109,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker)
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(exitOnError, "exit on error"),
INIT_PARAM_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
"result errors", false),
INIT_PARAM(function_trace, "Enable function trace"),
INIT_PARAM(function_trace_start, "Cycle to start function trace")
@@ -121,6 +127,7 @@ CREATE_SIM_OBJECT(O3Checker)
params->max_loads_any_thread = 0;
params->max_loads_all_threads = 0;
params->exitOnError = exitOnError;
params->warnOnlyOnLoadError = warnOnlyOnLoadError;
params->deferRegistration = defer_registration;
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;

View File

@@ -28,8 +28,7 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/commit_impl.hh"
template class DefaultCommit<AlphaSimpleImpl>;
template class DefaultCommit<O3CPUImpl>;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#ifndef __CPU_O3_COMMIT_HH__
@@ -67,7 +68,7 @@ class DefaultCommit
{
public:
// Typedefs from the Impl.
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::Params Params;
typedef typename Impl::CPUPol CPUPol;
@@ -145,7 +146,7 @@ class DefaultCommit
void regStats();
/** Sets the CPU pointer. */
void setCPU(FullCPU *cpu_ptr);
void setCPU(O3CPU *cpu_ptr);
/** Sets the list of threads. */
void setThreads(std::vector<Thread *> &threads);
@@ -161,10 +162,6 @@ class DefaultCommit
/** Sets the pointer to the queue coming from IEW. */
void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr);
void setFetchStage(Fetch *fetch_stage);
Fetch *fetchStage;
/** Sets the pointer to the IEW stage. */
void setIEWStage(IEW *iew_stage);
@@ -186,11 +183,14 @@ class DefaultCommit
/** Initializes stage by sending back the number of free entries. */
void initStage();
/** Initializes the switching out of commit. */
void switchOut();
/** Initializes the draining of commit. */
bool drain();
/** Resumes execution after draining. */
void resume();
/** Completes the switch out of commit. */
void doSwitchOut();
void switchOut();
/** Takes over from another CPU's thread. */
void takeOverFrom();
@@ -280,12 +280,20 @@ class DefaultCommit
/** Sets the PC of a specific thread. */
void setPC(uint64_t val, unsigned tid) { PC[tid] = val; }
/** Reads the PC of a specific thread. */
/** Reads the next PC of a specific thread. */
uint64_t readNextPC(unsigned tid) { return nextPC[tid]; }
/** Sets the next PC of a specific thread. */
void setNextPC(uint64_t val, unsigned tid) { nextPC[tid] = val; }
#if THE_ISA != ALPHA_ISA
/** Reads the next NPC of a specific thread. */
uint64_t readNextPC(unsigned tid) { return nextNPC[tid]; }
/** Sets the next NPC of a specific thread. */
void setNextPC(uint64_t val, unsigned tid) { nextNPC[tid] = val; }
#endif
private:
/** Time buffer interface. */
TimeBuffer<TimeStruct> *timeBuffer;
@@ -317,16 +325,12 @@ class DefaultCommit
ROB *rob;
private:
/** Pointer to FullCPU. */
FullCPU *cpu;
/** Pointer to O3CPU. */
O3CPU *cpu;
/** Vector of all of the threads. */
std::vector<Thread *> thread;
Fault fetchFault;
int fetchTrapWait;
/** Records that commit has written to the time buffer this cycle. Used for
* the CPU to determine if it can deschedule itself if there is no activity.
*/
@@ -365,11 +369,6 @@ class DefaultCommit
*/
unsigned renameWidth;
/** IEW width, in instructions. Used so ROB knows how many
* instructions to get from the IEW instruction queue.
*/
unsigned iewWidth;
/** Commit width, in instructions. */
unsigned commitWidth;
@@ -379,8 +378,8 @@ class DefaultCommit
/** Number of Active Threads */
unsigned numThreads;
/** Is a switch out pending. */
bool switchPending;
/** Is a drain pending. */
bool drainPending;
/** Is commit switched out. */
bool switchedOut;
@@ -390,10 +389,6 @@ class DefaultCommit
*/
Tick trapLatency;
Tick fetchTrapLatency;
Tick fetchFaultTick;
/** The commit PC of each thread. Refers to the instruction that
* is currently being processed/committed.
*/
@@ -402,6 +397,11 @@ class DefaultCommit
/** The next PC of each thread. */
Addr nextPC[Impl::MaxThreads];
#if THE_ISA != ALPHA_ISA
/** The next NPC of each thread. */
Addr nextNPC[Impl::MaxThreads];
#endif
/** The sequence number of the youngest valid instruction in the ROB. */
InstSeqNum youngestSeqNum[Impl::MaxThreads];

View File

@@ -28,16 +28,22 @@
* Authors: Kevin Lim
*/
#include "config/full_system.hh"
#include "config/use_checker.hh"
#include <algorithm>
#include <string>
#include "base/loader/symtab.hh"
#include "base/timebuf.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/exetrace.hh"
#include "cpu/o3/commit.hh"
#include "cpu/o3/thread_state.hh"
#if USE_CHECKER
#include "cpu/checker/cpu.hh"
#endif
using namespace std;
template <class Impl>
@@ -72,13 +78,11 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
renameToROBDelay(params->renameToROBDelay),
fetchToCommitDelay(params->commitToFetchDelay),
renameWidth(params->renameWidth),
iewWidth(params->executeWidth),
commitWidth(params->commitWidth),
numThreads(params->numberOfThreads),
switchPending(false),
drainPending(false),
switchedOut(false),
trapLatency(params->trapLatency),
fetchTrapLatency(params->fetchTrapLatency)
trapLatency(params->trapLatency)
{
_status = Active;
_nextStatus = Inactive;
@@ -118,9 +122,6 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
tcSquash[i] = false;
PC[i] = nextPC[i] = 0;
}
fetchFaultTick = 0;
fetchTrapWait = 0;
}
template <class Impl>
@@ -205,19 +206,6 @@ DefaultCommit<Impl>::regStats()
.flags(total)
;
//
// Commit-Eligible instructions...
//
// -> The number of instructions eligible to commit in those
// cycles where we reached our commit BW limit (less the number
// actually committed)
//
// -> The average value is computed over ALL CYCLES... not just
// the BW limited cycles
//
// -> The standard deviation is computed only over cycles where
// we reached the BW limit
//
commitEligible
.init(cpu->number_of_threads)
.name(name() + ".COM:bw_limited")
@@ -233,17 +221,16 @@ DefaultCommit<Impl>::regStats()
template <class Impl>
void
DefaultCommit<Impl>::setCPU(FullCPU *cpu_ptr)
DefaultCommit<Impl>::setCPU(O3CPU *cpu_ptr)
{
DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
cpu = cpu_ptr;
// Commit must broadcast the number of free entries it has at the start of
// the simulation, so it starts as active.
cpu->activateStage(FullCPU::CommitIdx);
cpu->activateStage(O3CPU::CommitIdx);
trapLatency = cpu->cycles(trapLatency);
fetchTrapLatency = cpu->cycles(fetchTrapLatency);
}
template <class Impl>
@@ -300,13 +287,6 @@ DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
fromIEW = iewQueue->getWire(-iewToCommitDelay);
}
template <class Impl>
void
DefaultCommit<Impl>::setFetchStage(Fetch *fetch_stage)
{
fetchStage = fetch_stage;
}
template <class Impl>
void
DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
@@ -358,21 +338,36 @@ DefaultCommit<Impl>::initStage()
}
template <class Impl>
void
DefaultCommit<Impl>::switchOut()
bool
DefaultCommit<Impl>::drain()
{
switchPending = true;
drainPending = true;
// If it's already drained, return true.
if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
cpu->signalDrained();
return true;
}
return false;
}
template <class Impl>
void
DefaultCommit<Impl>::doSwitchOut()
DefaultCommit<Impl>::switchOut()
{
switchedOut = true;
switchPending = false;
drainPending = false;
rob->switchOut();
}
template <class Impl>
void
DefaultCommit<Impl>::resume()
{
drainPending = false;
}
template <class Impl>
void
DefaultCommit<Impl>::takeOverFrom()
@@ -409,10 +404,10 @@ DefaultCommit<Impl>::updateStatus()
if (_nextStatus == Inactive && _status == Active) {
DPRINTF(Activity, "Deactivating stage.\n");
cpu->deactivateStage(FullCPU::CommitIdx);
cpu->deactivateStage(O3CPU::CommitIdx);
} else if (_nextStatus == Active && _status == Inactive) {
DPRINTF(Activity, "Activating stage.\n");
cpu->activateStage(FullCPU::CommitIdx);
cpu->activateStage(O3CPU::CommitIdx);
}
_status = _nextStatus;
@@ -434,7 +429,7 @@ DefaultCommit<Impl>::setNextStatus()
}
}
assert(squashes == squashCounter);
squashCounter = squashes;
// If commit is currently squashing, then it will have activity for the
// next cycle. Set its next status as active.
@@ -539,8 +534,6 @@ DefaultCommit<Impl>::squashFromTrap(unsigned tid)
commitStatus[tid] = ROBSquashing;
cpu->activityThisCycle();
++squashCounter;
}
template <class Impl>
@@ -558,8 +551,6 @@ DefaultCommit<Impl>::squashFromTC(unsigned tid)
cpu->activityThisCycle();
tcSquash[tid] = false;
++squashCounter;
}
template <class Impl>
@@ -569,11 +560,15 @@ DefaultCommit<Impl>::tick()
wroteToTimeBuffer = false;
_nextStatus = Inactive;
if (switchPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
cpu->signalSwitched();
if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
cpu->signalDrained();
drainPending = false;
return;
}
if ((*activeThreads).size() <= 0)
return;
list<unsigned>::iterator threads = (*activeThreads).begin();
// Check if any of the threads are done squashing. Change the
@@ -585,10 +580,12 @@ DefaultCommit<Impl>::tick()
if (rob->isDoneSquashing(tid)) {
commitStatus[tid] = Running;
--squashCounter;
} else {
DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
"insts this cycle.\n", tid);
" insts this cycle.\n", tid);
rob->doSquash(tid);
toIEW->commitInfo[tid].robSquashing = true;
wroteToTimeBuffer = true;
}
}
}
@@ -694,29 +691,7 @@ DefaultCommit<Impl>::commit()
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
/*
if (fromFetch->fetchFault && commitStatus[0] != TrapPending) {
// Record the fault. Wait until it's empty in the ROB.
// Then handle the trap. Ignore it if there's already a
// trap pending as fetch will be redirected.
fetchFault = fromFetch->fetchFault;
fetchFaultTick = curTick + fetchTrapLatency;
commitStatus[0] = FetchTrapPending;
DPRINTF(Commit, "Fault from fetch recorded. Will trap if the "
"ROB empties without squashing the fault.\n");
fetchTrapWait = 0;
}
// Fetch may tell commit to clear the trap if it's been squashed.
if (fromFetch->clearFetchFault) {
DPRINTF(Commit, "Received clear fetch fault signal\n");
fetchTrapWait = 0;
if (commitStatus[0] == FetchTrapPending) {
DPRINTF(Commit, "Clearing fault from fetch\n");
commitStatus[0] = Running;
}
}
*/
// Not sure which one takes priority. I think if we have
// both, that's a bad sign.
if (trapSquash[tid] == true) {
@@ -744,8 +719,6 @@ DefaultCommit<Impl>::commit()
commitStatus[tid] = ROBSquashing;
++squashCounter;
// If we want to include the squashing instruction in the squash,
// then use one older sequence number.
InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
@@ -947,7 +920,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
// and committed this instruction.
thread[tid]->funcExeInst--;
head_inst->reachedCommit = true;
head_inst->setAtCommit();
if (head_inst->isNonSpeculative() ||
head_inst->isStoreConditional() ||
@@ -1012,18 +985,19 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
head_inst->setCompleted();
}
#if USE_CHECKER
// Use checker prior to updating anything due to traps or PC
// based events.
if (cpu->checker) {
cpu->checker->tick(head_inst);
cpu->checker->verify(head_inst);
}
#endif
// Check if the instruction caused a fault. If so, trap.
Fault inst_fault = head_inst->getFault();
if (inst_fault != NoFault) {
head_inst->setCompleted();
#if FULL_SYSTEM
DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
head_inst->seqNum, head_inst->readPC());
@@ -1032,9 +1006,11 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
return false;
}
#if USE_CHECKER
if (cpu->checker && head_inst->isStore()) {
cpu->checker->tick(head_inst);
cpu->checker->verify(head_inst);
}
#endif
assert(!thread[tid]->inSyscall);
@@ -1065,10 +1041,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
generateTrapEvent(tid);
return false;
#else // !FULL_SYSTEM
panic("fault (%d) detected @ PC %08p", inst_fault,
head_inst->PC);
#endif // FULL_SYSTEM
}
updateComInstStats(head_inst);
@@ -1256,7 +1228,8 @@ DefaultCommit<Impl>::roundRobin()
unsigned tid = *pri_iter;
if (commitStatus[tid] == Running ||
commitStatus[tid] == Idle) {
commitStatus[tid] == Idle ||
commitStatus[tid] == FetchTrapPending) {
if (rob->isHeadReady(tid)) {
priority_list.erase(pri_iter);

View File

@@ -26,9 +26,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#include "config/full_system.hh"
#include "config/use_checker.hh"
#if FULL_SYSTEM
#include "sim/system.hh"
@@ -37,26 +39,28 @@
#endif
#include "cpu/activity.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/cpu.hh"
#include "sim/root.hh"
#include "sim/stat_control.hh"
#if USE_CHECKER
#include "cpu/checker/cpu.hh"
#endif
using namespace std;
using namespace TheISA;
BaseFullCPU::BaseFullCPU(Params *params)
BaseO3CPU::BaseO3CPU(Params *params)
: BaseCPU(params), cpu_id(0)
{
}
void
BaseFullCPU::regStats()
BaseO3CPU::regStats()
{
BaseCPU::regStats();
}
@@ -81,9 +85,68 @@ FullO3CPU<Impl>::TickEvent::description()
return "FullO3CPU tick event";
}
template <class Impl>
FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
: Event(&mainEventQueue, CPU_Tick_Pri)
{
}
template <class Impl>
void
FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num,
FullO3CPU<Impl> *thread_cpu)
{
tid = thread_num;
cpu = thread_cpu;
}
template <class Impl>
void
FullO3CPU<Impl>::ActivateThreadEvent::process()
{
cpu->activateThread(tid);
}
template <class Impl>
const char *
FullO3CPU<Impl>::ActivateThreadEvent::description()
{
return "FullO3CPU \"Activate Thread\" event";
}
template <class Impl>
FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
: Event(&mainEventQueue, CPU_Tick_Pri)
{
}
template <class Impl>
void
FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
FullO3CPU<Impl> *thread_cpu)
{
tid = thread_num;
cpu = thread_cpu;
}
template <class Impl>
void
FullO3CPU<Impl>::DeallocateContextEvent::process()
{
cpu->deactivateThread(tid);
cpu->removeThread(tid);
}
template <class Impl>
const char *
FullO3CPU<Impl>::DeallocateContextEvent::description()
{
return "FullO3CPU \"Deallocate Context\" event";
}
template <class Impl>
FullO3CPU<Impl>::FullO3CPU(Params *params)
: BaseFullCPU(params),
: BaseO3CPU(params),
tickEvent(this),
removeInstsThisCycle(false),
fetch(params),
@@ -94,7 +157,7 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
freeList(params->numberOfThreads,//number of activeThreads
freeList(params->numberOfThreads,
TheISA::NumIntRegs, params->numPhysIntRegs,
TheISA::NumFloatRegs, params->numPhysFloatRegs),
@@ -102,21 +165,20 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
params->smtROBPolicy, params->smtROBThreshold,
params->numberOfThreads),
scoreboard(params->numberOfThreads,//number of activeThreads
scoreboard(params->numberOfThreads,
TheISA::NumIntRegs, params->numPhysIntRegs,
TheISA::NumFloatRegs, params->numPhysFloatRegs,
TheISA::NumMiscRegs * number_of_threads,
TheISA::ZeroReg),
// For now just have these time buffers be pretty big.
// @todo: Make these time buffer sizes parameters or derived
// from latencies
timeBuffer(5, 5),
fetchQueue(5, 5),
decodeQueue(5, 5),
renameQueue(5, 5),
iewQueue(5, 5),
activityRec(NumStages, 10, params->activity),
timeBuffer(params->backComSize, params->forwardComSize),
fetchQueue(params->backComSize, params->forwardComSize),
decodeQueue(params->backComSize, params->forwardComSize),
renameQueue(params->backComSize, params->forwardComSize),
iewQueue(params->backComSize, params->forwardComSize),
activityRec(NumStages,
params->backComSize + params->forwardComSize,
params->activity),
globalSeqNum(1),
@@ -125,21 +187,25 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
physmem(system->physmem),
#endif // FULL_SYSTEM
mem(params->mem),
switchCount(0),
drainCount(0),
deferRegistration(params->deferRegistration),
numThreads(number_of_threads)
{
_status = Idle;
checker = NULL;
if (params->checker) {
#if USE_CHECKER
BaseCPU *temp_checker = params->checker;
checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
checker->setMemory(mem);
#if FULL_SYSTEM
checker->setSystem(params->system);
#endif
} else {
checker = NULL;
#else
panic("Checker enabled but not compiled in!");
#endif // USE_CHECKER
}
#if !FULL_SYSTEM
@@ -177,13 +243,18 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
commit.setIEWQueue(&iewQueue);
commit.setRenameQueue(&renameQueue);
commit.setFetchStage(&fetch);
commit.setIEWStage(&iew);
rename.setIEWStage(&iew);
rename.setCommitStage(&commit);
#if !FULL_SYSTEM
int active_threads = params->workload.size();
if (active_threads > Impl::MaxThreads) {
panic("Workload Size too large. Increase the 'MaxThreads'"
"constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or "
"edit your workload size.");
}
#else
int active_threads = 1;
#endif
@@ -249,6 +320,8 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
lastRunningCycle = curTick;
lastActivatedCycle = -1;
contextSwitch = false;
}
@@ -261,9 +334,9 @@ template <class Impl>
void
FullO3CPU<Impl>::fullCPURegStats()
{
BaseFullCPU::regStats();
BaseO3CPU::regStats();
// Register any of the FullCPU's stats here.
// Register any of the O3CPU's stats here.
timesIdled
.name(name() + ".timesIdled")
.desc("Number of times that the entire CPU went into an idle state and"
@@ -315,11 +388,23 @@ FullO3CPU<Impl>::fullCPURegStats()
}
template <class Impl>
Port *
FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
{
if (if_name == "dcache_port")
return iew.getDcachePort();
else if (if_name == "icache_port")
return fetch.getIcachePort();
else
panic("No Such Port\n");
}
template <class Impl>
void
FullO3CPU<Impl>::tick()
{
DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
++numCycles;
@@ -355,7 +440,8 @@ FullO3CPU<Impl>::tick()
}
if (!tickEvent.scheduled()) {
if (_status == SwitchedOut) {
if (_status == SwitchedOut ||
getState() == SimObject::Drained) {
// increment stat
lastRunningCycle = curTick;
} else if (!activityRec.active()) {
@@ -414,18 +500,109 @@ FullO3CPU<Impl>::init()
commit.setThreads(thread);
}
template <class Impl>
void
FullO3CPU<Impl>::activateThread(unsigned tid)
{
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive == activeThreads.end()) {
DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
tid);
activeThreads.push_back(tid);
}
}
template <class Impl>
void
FullO3CPU<Impl>::deactivateThread(unsigned tid)
{
//Remove From Active List, if Active
list<unsigned>::iterator thread_it =
find(activeThreads.begin(), activeThreads.end(), tid);
if (thread_it != activeThreads.end()) {
DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(thread_it);
}
}
template <class Impl>
void
FullO3CPU<Impl>::activateContext(int tid, int delay)
{
// Needs to set each stage to running as well.
if (delay){
DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
"on cycle %d\n", tid, curTick + cycles(delay));
scheduleActivateThreadEvent(tid, delay);
} else {
activateThread(tid);
}
if(lastActivatedCycle < curTick) {
scheduleTickEvent(delay);
// Be sure to signal that there's some activity so the CPU doesn't
// deschedule itself.
activityRec.activity();
fetch.wakeFromQuiesce();
lastActivatedCycle = curTick;
_status = Running;
}
}
template <class Impl>
void
FullO3CPU<Impl>::deallocateContext(int tid, int delay)
{
// Schedule removal of thread data from CPU
if (delay){
DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
"on cycle %d\n", tid, curTick + cycles(delay));
scheduleDeallocateContextEvent(tid, delay);
} else {
deactivateThread(tid);
removeThread(tid);
}
}
template <class Impl>
void
FullO3CPU<Impl>::suspendContext(int tid)
{
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
deactivateThread(tid);
if (activeThreads.size() == 0)
unscheduleTickEvent();
_status = Idle;
}
template <class Impl>
void
FullO3CPU<Impl>::haltContext(int tid)
{
//For now, this is the same as deallocate
DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
deallocateContext(tid, 1);
}
template <class Impl>
void
FullO3CPU<Impl>::insertThread(unsigned tid)
{
DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
// Will change now that the PC and thread state is internal to the CPU
// and not in the ThreadContext.
#if 0
#if FULL_SYSTEM
ThreadContext *src_tc = system->threadContexts[tid];
#else
ThreadContext *src_tc = thread[tid];
ThreadContext *src_tc = tcBase(tid);
#endif
//Bind Int Regs to Rename Map
@@ -445,11 +622,14 @@ FullO3CPU<Impl>::insertThread(unsigned tid)
}
//Copy Thread Data Into RegFile
this->copyFromTC(tid);
//this->copyFromTC(tid);
//Set PC/NPC
regFile.pc[tid] = src_tc->readPC();
regFile.npc[tid] = src_tc->readNextPC();
//Set PC/NPC/NNPC
setPC(src_tc->readPC(), tid);
setNextPC(src_tc->readNextPC(), tid);
#if THE_ISA != ALPHA_ISA
setNextNPC(src_tc->readNextNPC(), tid);
#endif
src_tc->setStatus(ThreadContext::Active);
@@ -458,16 +638,19 @@ FullO3CPU<Impl>::insertThread(unsigned tid)
//Reset ROB/IQ/LSQ Entries
commit.rob->resetEntries();
iew.resetEntries();
#endif
}
template <class Impl>
void
FullO3CPU<Impl>::removeThread(unsigned tid)
{
DPRINTF(FullCPU,"[tid:%i] Removing thread data");
#if 0
//Unbind Int Regs from Rename Map
DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
// Copy Thread Data From RegFile
// If thread is suspended, it might be re-allocated
//this->copyToTC(tid);
// Unbind Int Regs from Rename Map
for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
@@ -475,7 +658,7 @@ FullO3CPU<Impl>::removeThread(unsigned tid)
freeList.addReg(phys_reg);
}
//Unbind Float Regs from Rename Map
// Unbind Float Regs from Rename Map
for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
@@ -483,27 +666,20 @@ FullO3CPU<Impl>::removeThread(unsigned tid)
freeList.addReg(phys_reg);
}
//Copy Thread Data From RegFile
/* Fix Me:
* Do we really need to do this if we are removing a thread
* in the sense that it's finished (exiting)? If the thread is just
* being suspended we might...
*/
// this->copyToTC(tid);
//Squash Throughout Pipeline
// Squash Throughout Pipeline
fetch.squash(0,tid);
decode.squash(tid);
rename.squash(tid);
iew.squash(tid);
commit.rob->squash(commit.rob->readHeadInst(tid)->seqNum, tid);
assert(iew.ldstQueue.getCount(tid) == 0);
//Reset ROB/IQ/LSQ Entries
// Reset ROB/IQ/LSQ Entries
if (activeThreads.size() >= 1) {
commit.rob->resetEntries();
iew.resetEntries();
}
#endif
}
@@ -511,37 +687,37 @@ template <class Impl>
void
FullO3CPU<Impl>::activateWhenReady(int tid)
{
DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
"(e.g. PhysRegs/ROB/IQ/LSQ) \n",
tid);
bool ready = true;
if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"Phys. Int. Regs.\n",
tid);
ready = false;
} else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"Phys. Float. Regs.\n",
tid);
ready = false;
} else if (commit.rob->numFreeEntries() >=
commit.rob->entryAmount(activeThreads.size() + 1)) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"ROB entries.\n",
tid);
ready = false;
} else if (iew.instQueue.numFreeEntries() >=
iew.instQueue.entryAmount(activeThreads.size() + 1)) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"IQ entries.\n",
tid);
ready = false;
} else if (iew.ldstQueue.numFreeEntries() >=
iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
"LSQ entries.\n",
tid);
ready = false;
@@ -559,6 +735,7 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
//blocks fetch
contextSwitch = true;
//@todo: dont always add to waitlist
//do waitlist
cpuWaitList.push_back(tid);
}
@@ -566,133 +743,130 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
template <class Impl>
void
FullO3CPU<Impl>::activateContext(int tid, int delay)
FullO3CPU<Impl>::serialize(std::ostream &os)
{
// Needs to set each stage to running as well.
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
SERIALIZE_ENUM(_status);
BaseCPU::serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
if (isActive == activeThreads.end()) {
//May Need to Re-code this if the delay variable is the
//delay needed for thread to activate
DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
tid);
// Use SimpleThread's ability to checkpoint to make it easier to
// write out the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
static SimpleThread temp;
activeThreads.push_back(tid);
for (int i = 0; i < thread.size(); i++) {
nameOut(os, csprintf("%s.xc.%i", name(), i));
temp.copyTC(thread[i]->getTC());
temp.serialize(os);
}
}
assert(_status == Idle || _status == SwitchedOut);
template <class Impl>
void
FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ENUM(_status);
BaseCPU::unserialize(cp, section);
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
scheduleTickEvent(delay);
// Use SimpleThread's ability to checkpoint to make it easier to
// read in the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
static SimpleThread temp;
// Be sure to signal that there's some activity so the CPU doesn't
// deschedule itself.
activityRec.activity();
fetch.wakeFromQuiesce();
for (int i = 0; i < thread.size(); i++) {
temp.copyTC(thread[i]->getTC());
temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
thread[i]->getTC()->copyArchRegs(temp.getTC());
}
}
template <class Impl>
unsigned int
FullO3CPU<Impl>::drain(Event *drain_event)
{
drainCount = 0;
fetch.drain();
decode.drain();
rename.drain();
iew.drain();
commit.drain();
// Wake the CPU and record activity so everything can drain out if
// the CPU was not able to immediately drain.
if (getState() != SimObject::Drained) {
// A bit of a hack...set the drainEvent after all the drain()
// calls have been made, that way if all of the stages drain
// immediately, the signalDrained() function knows not to call
// process on the drain event.
drainEvent = drain_event;
wakeCPU();
activityRec.activity();
return 1;
} else {
return 0;
}
}
template <class Impl>
void
FullO3CPU<Impl>::resume()
{
assert(system->getMemoryMode() == System::Timing);
fetch.resume();
decode.resume();
rename.resume();
iew.resume();
commit.resume();
changeState(SimObject::Running);
if (_status == SwitchedOut || _status == Idle)
return;
if (!tickEvent.scheduled())
tickEvent.schedule(curTick);
_status = Running;
}
template <class Impl>
void
FullO3CPU<Impl>::suspendContext(int tid)
FullO3CPU<Impl>::signalDrained()
{
DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
unscheduleTickEvent();
_status = Idle;
/*
//Remove From Active List, if Active
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive != activeThreads.end()) {
DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(isActive);
}
*/
}
template <class Impl>
void
FullO3CPU<Impl>::deallocateContext(int tid)
{
DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
/*
//Remove From Active List, if Active
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive != activeThreads.end()) {
DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(isActive);
removeThread(tid);
}
*/
}
template <class Impl>
void
FullO3CPU<Impl>::haltContext(int tid)
{
DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
/*
//Remove From Active List, if Active
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive != activeThreads.end()) {
DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
tid);
activeThreads.erase(isActive);
removeThread(tid);
}
*/
}
template <class Impl>
void
FullO3CPU<Impl>::switchOut(Sampler *_sampler)
{
sampler = _sampler;
switchCount = 0;
fetch.switchOut();
decode.switchOut();
rename.switchOut();
iew.switchOut();
commit.switchOut();
// Wake the CPU and record activity so everything can drain out if
// the CPU is currently idle.
wakeCPU();
activityRec.activity();
}
template <class Impl>
void
FullO3CPU<Impl>::signalSwitched()
{
if (++switchCount == NumStages) {
fetch.doSwitchOut();
rename.doSwitchOut();
commit.doSwitchOut();
instList.clear();
while (!removeList.empty()) {
removeList.pop();
}
if (checker)
checker->switchOut(sampler);
if (++drainCount == NumStages) {
if (tickEvent.scheduled())
tickEvent.squash();
sampler->signalSwitched();
_status = SwitchedOut;
changeState(SimObject::Drained);
if (drainEvent) {
drainEvent->process();
drainEvent = NULL;
}
}
assert(switchCount <= 5);
assert(drainCount <= 5);
}
template <class Impl>
void
FullO3CPU<Impl>::switchOut()
{
fetch.switchOut();
rename.switchOut();
commit.switchOut();
instList.clear();
while (!removeList.empty()) {
removeList.pop();
}
_status = SwitchedOut;
#if USE_CHECKER
if (checker)
checker->switchOut();
#endif
}
template <class Impl>
@@ -700,7 +874,7 @@ void
FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
{
// Flush out any old data from the time buffers.
for (int i = 0; i < 10; ++i) {
for (int i = 0; i < timeBuffer.getSize(); ++i) {
timeBuffer.advance();
fetchQueue.advance();
decodeQueue.advance();
@@ -730,7 +904,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
if (isActive == activeThreads.end()) {
//May Need to Re-code this if the delay variable is the delay
//needed for thread to activate
DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
tid);
activeThreads.push_back(tid);
@@ -922,6 +1096,22 @@ FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
commit.setNextPC(val, tid);
}
#if THE_ISA != ALPHA_ISA
template <class Impl>
uint64_t
FullO3CPU<Impl>::readNextNPC(unsigned tid)
{
return commit.readNextNPC(tid);
}
template <class Impl>
void
FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid)
{
commit.setNextNPC(val, tid);
}
#endif
template <class Impl>
typename FullO3CPU<Impl>::ListIt
FullO3CPU<Impl>::addInst(DynInstPtr &inst)
@@ -958,7 +1148,7 @@ template <class Impl>
void
FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
{
DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x "
"[sn:%lli]\n",
inst->threadNumber, inst->readPC(), inst->seqNum);
@@ -972,7 +1162,7 @@ template <class Impl>
void
FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
{
DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
" list.\n", tid);
ListIt end_it;
@@ -982,12 +1172,12 @@ FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
if (instList.empty()) {
return;
} else if (rob.isEmpty(/*tid*/)) {
DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
end_it = instList.begin();
rob_empty = true;
} else {
end_it = (rob.readTailInst(tid))->getInstListIt();
DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
}
removeInstsThisCycle = true;
@@ -1026,7 +1216,7 @@ FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
inst_iter--;
DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
DPRINTF(O3CPU, "Deleting instructions from instruction "
"list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
tid, seq_num, (*inst_iter)->seqNum);
@@ -1048,7 +1238,7 @@ inline void
FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
{
if ((*instIt)->threadNumber == tid) {
DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
DPRINTF(O3CPU, "Squashing instruction, "
"[tid:%i] [sn:%lli] PC %#x\n",
(*instIt)->threadNumber,
(*instIt)->seqNum,
@@ -1069,7 +1259,7 @@ void
FullO3CPU<Impl>::cleanUpRemovedInsts()
{
while (!removeList.empty()) {
DPRINTF(FullCPU, "FullCPU: Removing instruction, "
DPRINTF(O3CPU, "Removing instruction, "
"[tid:%i] [sn:%lli] PC %#x\n",
(*removeList.front())->threadNumber,
(*removeList.front())->seqNum,
@@ -1185,4 +1375,4 @@ FullO3CPU<Impl>::updateThreadPriority()
}
// Forward declaration of FullO3CPU.
template class FullO3CPU<AlphaSimpleImpl>;
template class FullO3CPU<O3CPUImpl>;

View File

@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
* Korey Sewell
*/
#ifndef __CPU_O3_CPU_HH__
@@ -48,24 +49,33 @@
#include "cpu/o3/cpu_policy.hh"
#include "cpu/o3/scoreboard.hh"
#include "cpu/o3/thread_state.hh"
//#include "cpu/o3/thread_context.hh"
#include "sim/process.hh"
template <class>
class Checker;
class ThreadContext;
template <class>
class O3ThreadContext;
class Checkpoint;
class MemObject;
class Process;
class BaseFullCPU : public BaseCPU
class BaseO3CPU : public BaseCPU
{
//Stuff that's pretty ISA independent will go here.
public:
typedef BaseCPU::Params Params;
BaseFullCPU(Params *params);
BaseO3CPU(Params *params);
void regStats();
/** Sets this CPU's ID. */
void setCpuId(int id) { cpu_id = id; }
/** Reads this CPU's ID. */
int readCpuId() { return cpu_id; }
protected:
@@ -78,7 +88,7 @@ class BaseFullCPU : public BaseCPU
* tick() function for the CPU is defined here.
*/
template <class Impl>
class FullO3CPU : public BaseFullCPU
class FullO3CPU : public BaseO3CPU
{
public:
typedef TheISA::FloatReg FloatReg;
@@ -93,6 +103,8 @@ class FullO3CPU : public BaseFullCPU
typedef typename std::list<DynInstPtr>::iterator ListIt;
friend class O3ThreadContext<Impl>;
public:
enum Status {
Running,
@@ -105,6 +117,9 @@ class FullO3CPU : public BaseFullCPU
/** Overall CPU status. */
Status _status;
/** Per-thread status in CPU, used for SMT. */
Status _threadStatus[Impl::MaxThreads];
private:
class TickEvent : public Event
{
@@ -141,6 +156,92 @@ class FullO3CPU : public BaseFullCPU
tickEvent.squash();
}
class ActivateThreadEvent : public Event
{
private:
/** Number of Thread to Activate */
int tid;
/** Pointer to the CPU. */
FullO3CPU<Impl> *cpu;
public:
/** Constructs the event. */
ActivateThreadEvent();
/** Initialize Event */
void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
/** Processes the event, calling activateThread() on the CPU. */
void process();
/** Returns the description of the event. */
const char *description();
};
/** Schedule thread to activate , regardless of its current state. */
void scheduleActivateThreadEvent(int tid, int delay)
{
// Schedule thread to activate, regardless of its current state.
if (activateThreadEvent[tid].squashed())
activateThreadEvent[tid].reschedule(curTick + cycles(delay));
else if (!activateThreadEvent[tid].scheduled())
activateThreadEvent[tid].schedule(curTick + cycles(delay));
}
/** Unschedule actiavte thread event, regardless of its current state. */
void unscheduleActivateThreadEvent(int tid)
{
if (activateThreadEvent[tid].scheduled())
activateThreadEvent[tid].squash();
}
/** The tick event used for scheduling CPU ticks. */
ActivateThreadEvent activateThreadEvent[Impl::MaxThreads];
class DeallocateContextEvent : public Event
{
private:
/** Number of Thread to Activate */
int tid;
/** Pointer to the CPU. */
FullO3CPU<Impl> *cpu;
public:
/** Constructs the event. */
DeallocateContextEvent();
/** Initialize Event */
void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
/** Processes the event, calling activateThread() on the CPU. */
void process();
/** Returns the description of the event. */
const char *description();
};
/** Schedule cpu to deallocate thread context.*/
void scheduleDeallocateContextEvent(int tid, int delay)
{
// Schedule thread to activate, regardless of its current state.
if (deallocateContextEvent[tid].squashed())
deallocateContextEvent[tid].reschedule(curTick + cycles(delay));
else if (!deallocateContextEvent[tid].scheduled())
deallocateContextEvent[tid].schedule(curTick + cycles(delay));
}
/** Unschedule thread deallocation in CPU */
void unscheduleDeallocateContextEvent(int tid)
{
if (deallocateContextEvent[tid].scheduled())
deallocateContextEvent[tid].squash();
}
/** The tick event used for scheduling CPU ticks. */
DeallocateContextEvent deallocateContextEvent[Impl::MaxThreads];
public:
/** Constructs a CPU with the given parameters. */
FullO3CPU(Params *params);
@@ -150,6 +251,9 @@ class FullO3CPU : public BaseFullCPU
/** Registers statistics. */
void fullCPURegStats();
/** Returns a specific port. */
Port *getPort(const std::string &if_name, int idx);
/** Ticks CPU, calling tick() on each stage, and checking the overall
* activity to see if the CPU should deschedule itself.
*/
@@ -158,6 +262,16 @@ class FullO3CPU : public BaseFullCPU
/** Initialize the CPU */
void init();
/** Returns the Number of Active Threads in the CPU */
int numActiveThreads()
{ return activeThreads.size(); }
/** Add Thread to Active Threads List */
void activateThread(unsigned tid);
/** Remove Thread from Active Threads List */
void deactivateThread(unsigned tid);
/** Setup CPU to insert a thread's context */
void insertThread(unsigned tid);
@@ -184,7 +298,7 @@ class FullO3CPU : public BaseFullCPU
/** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU.
*/
void deallocateContext(int tid);
void deallocateContext(int tid, int delay = 1);
/** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU.
@@ -200,6 +314,13 @@ class FullO3CPU : public BaseFullCPU
/** Update The Order In Which We Process Threads. */
void updateThreadPriority();
/** Serialize state. */
virtual void serialize(std::ostream &os);
/** Unserialize from a checkpoint. */
virtual void unserialize(Checkpoint *cp, const std::string &section);
public:
/** Executes a syscall on this cycle.
* ---------------------------------------
* Note: this is a virtual function. CPU-Specific
@@ -207,14 +328,21 @@ class FullO3CPU : public BaseFullCPU
*/
virtual void syscall(int tid) { panic("Unimplemented!"); }
/** Switches out this CPU. */
void switchOut(Sampler *sampler);
/** Starts draining the CPU's pipeline of all instructions in
* order to stop all memory accesses. */
virtual unsigned int drain(Event *drain_event);
/** Resumes execution after a drain. */
virtual void resume();
/** Signals to this CPU that a stage has completed switching out. */
void signalSwitched();
void signalDrained();
/** Switches out this CPU. */
virtual void switchOut();
/** Takes over from another CPU. */
void takeOverFrom(BaseCPU *oldCPU);
virtual void takeOverFrom(BaseCPU *oldCPU);
/** Get the current instruction sequence number, and increment it. */
InstSeqNum getAndIncrementInstSeq()
@@ -299,6 +427,12 @@ class FullO3CPU : public BaseFullCPU
/** Sets the next PC of a specific thread. */
void setNextPC(uint64_t val, unsigned tid);
/** Reads the next NPC of a specific thread. */
uint64_t readNextNPC(unsigned tid);
/** Sets the next NPC of a specific thread. */
void setNextNPC(uint64_t val, unsigned tid);
/** Function to add instruction onto the head of the list of the
* instructions. Used when new instructions are fetched.
*/
@@ -481,11 +615,11 @@ class FullO3CPU : public BaseFullCPU
/** Pointer to memory. */
MemObject *mem;
/** Pointer to the sampler */
Sampler *sampler;
/** Event to call process() on once draining has completed. */
Event *drainEvent;
/** Counter of how many stages have completed switching out. */
int switchCount;
/** Counter of how many stages have completed draining. */
int drainCount;
/** Pointers to all of the threads in the CPU. */
std::vector<Thread *> thread;
@@ -507,6 +641,9 @@ class FullO3CPU : public BaseFullCPU
/** The cycle that the CPU was last running, used for statistics. */
Tick lastRunningCycle;
/** The cycle that the CPU was last activated by a new thread*/
Tick lastActivatedCycle;
/** Number of Threads CPU can process */
unsigned numThreads;

View File

@@ -28,8 +28,7 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/decode_impl.hh"
template class DefaultDecode<AlphaSimpleImpl>;
template class DefaultDecode<O3CPUImpl>;

View File

@@ -48,7 +48,7 @@ class DefaultDecode
{
private:
// Typedefs from the Impl.
typedef typename Impl::FullCPU FullCPU;
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::Params Params;
typedef typename Impl::CPUPol CPUPol;
@@ -95,7 +95,7 @@ class DefaultDecode
void regStats();
/** Sets CPU pointer. */
void setCPU(FullCPU *cpu_ptr);
void setCPU(O3CPU *cpu_ptr);
/** Sets the main backwards communication time buffer pointer. */
void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
@@ -109,8 +109,14 @@ class DefaultDecode
/** Sets pointer to list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
/** Drains the decode stage. */
bool drain();
/** Resumes execution after a drain. */
void resume() { }
/** Switches out the decode stage. */
void switchOut();
void switchOut() { }
/** Takes over from another CPU's thread. */
void takeOverFrom();
@@ -189,7 +195,7 @@ class DefaultDecode
private:
// Interfaces to objects outside of decode.
/** CPU interface. */
FullCPU *cpu;
O3CPU *cpu;
/** Time buffer interface. */
TimeBuffer<TimeStruct> *timeBuffer;

View File

@@ -112,7 +112,7 @@ DefaultDecode<Impl>::regStats()
template<class Impl>
void
DefaultDecode<Impl>::setCPU(FullCPU *cpu_ptr)
DefaultDecode<Impl>::setCPU(O3CPU *cpu_ptr)
{
DPRINTF(Decode, "Setting CPU pointer.\n");
cpu = cpu_ptr;
@@ -165,11 +165,12 @@ DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
}
template <class Impl>
void
DefaultDecode<Impl>::switchOut()
bool
DefaultDecode<Impl>::drain()
{
// Decode can immediately switch out.
cpu->signalSwitched();
// Decode is done draining at any time.
cpu->signalDrained();
return true;
}
template <class Impl>
@@ -296,7 +297,7 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
for (int i=0; i<fromFetch->size; i++) {
if (fromFetch->insts[i]->threadNumber == tid &&
fromFetch->insts[i]->seqNum > inst->seqNum) {
fromFetch->insts[i]->squashed = true;
fromFetch->insts[i]->setSquashed();
}
}
@@ -345,7 +346,7 @@ DefaultDecode<Impl>::squash(unsigned tid)
for (int i=0; i<fromFetch->size; i++) {
if (fromFetch->insts[i]->threadNumber == tid) {
fromFetch->insts[i]->squashed = true;
fromFetch->insts[i]->setSquashed();
squash_count++;
}
}
@@ -427,7 +428,7 @@ DefaultDecode<Impl>::updateStatus()
DPRINTF(Activity, "Activating stage.\n");
cpu->activateStage(FullCPU::DecodeIdx);
cpu->activateStage(O3CPU::DecodeIdx);
}
} else {
// If it's not unblocking, then decode will not have any internal
@@ -436,7 +437,7 @@ DefaultDecode<Impl>::updateStatus()
_status = Inactive;
DPRINTF(Activity, "Deactivating stage.\n");
cpu->deactivateStage(FullCPU::DecodeIdx);
cpu->deactivateStage(O3CPU::DecodeIdx);
}
}
}
@@ -515,7 +516,7 @@ DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
// Check ROB squash signals from commit.
if (fromCommit->commitInfo[tid].robSquashing) {
DPRINTF(Decode, "[tid:%]: ROB is still squashing.\n",tid);
DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid);
// Continue to squash.
decodeStatus[tid] = Squashing;

View File

@@ -68,6 +68,8 @@ class DependencyGraph
: numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)
{ }
~DependencyGraph();
/** Resize the dependency graph to have num_entries registers. */
void resize(int num_entries);
@@ -120,6 +122,12 @@ class DependencyGraph
uint64_t nodesRemoved;
};
template <class DynInstPtr>
DependencyGraph<DynInstPtr>::~DependencyGraph()
{
delete [] dependGraph;
}
template <class DynInstPtr>
void
DependencyGraph<DynInstPtr>::resize(int num_entries)

45
src/cpu/o3/dyn_inst.hh Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2006 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: Korey Sewell
*/
#ifndef __CPU_O3_DYN_INST_HH__
#define __CPU_O3_DYN_INST_HH__
#include "arch/isa_specific.hh"
#if THE_ISA == ALPHA_ISA
template <class Impl>
class AlphaDynInst;
struct AlphaSimpleImpl;
typedef AlphaDynInst<AlphaSimpleImpl> O3DynInst;
#endif
#endif // __CPU_O3_DYN_INST_HH__

View File

@@ -28,8 +28,7 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/isa_specific.hh"
#include "cpu/o3/fetch_impl.hh"
template class DefaultFetch<AlphaSimpleImpl>;
template class DefaultFetch<O3CPUImpl>;

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