Merge m5.eecs.umich.edu:/bk/newmem
into ewok.(none):/home/gblack/m5/newmem --HG-- extra : convert_revision : 516c357f98c7a571c70362babd3fa162fbc2ed5a
This commit is contained in:
42
AUTHORS
Normal file
42
AUTHORS
Normal 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
88
README
@@ -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).
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
29
SConstruct
29
SConstruct
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 })
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -112,6 +112,10 @@ namespace AlphaISA
|
||||
lock_flag = 0;
|
||||
lock_addr = 0;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
#if FULL_SYSTEM
|
||||
protected:
|
||||
typedef uint64_t InternalProcReg;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}};
|
||||
|
||||
|
||||
@@ -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')
|
||||
}};
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 §ion)
|
||||
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 §ion)
|
||||
{
|
||||
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
|
||||
|
||||
@@ -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 ®_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__
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -50,6 +50,9 @@ class MipsLiveProcess : public LiveProcess
|
||||
std::vector<std::string> &envp);
|
||||
|
||||
void startup();
|
||||
|
||||
|
||||
static Addr stack_start;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 §ion);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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']
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
*/
|
||||
@@ -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> > >;
|
||||
|
||||
@@ -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
458
src/cpu/checker/cpu_impl.hh
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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' })
|
||||
|
||||
@@ -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
161
src/cpu/exec_context.hh
Normal 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
171
src/cpu/func_unit.cc
Normal 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
101
src/cpu/func_unit.hh
Normal 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
79
src/cpu/o3/SConscript
Executable 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')
|
||||
|
||||
@@ -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
204
src/cpu/o3/alpha/cpu.hh
Normal 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__
|
||||
@@ -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)
|
||||
|
||||
422
src/cpu/o3/alpha/cpu_impl.hh
Normal file
422
src/cpu/o3/alpha/cpu_impl.hh
Normal 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
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__
|
||||
60
src/cpu/o3/alpha/params.hh
Normal file
60
src/cpu/o3/alpha/params.hh
Normal 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__
|
||||
36
src/cpu/o3/alpha/thread_context.cc
Executable file
36
src/cpu/o3/alpha/thread_context.cc
Executable 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>;
|
||||
|
||||
88
src/cpu/o3/alpha/thread_context.hh
Normal file
88
src/cpu/o3/alpha/thread_context.hh
Normal 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
|
||||
}
|
||||
};
|
||||
@@ -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 §ion);
|
||||
|
||||
#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__
|
||||
@@ -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 §ion)
|
||||
{
|
||||
#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
|
||||
39
src/cpu/o3/base_dyn_inst.cc
Normal file
39
src/cpu/o3/base_dyn_inst.cc
Normal 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;
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
@@ -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>;
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 §ion)
|
||||
{
|
||||
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>;
|
||||
|
||||
@@ -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 §ion);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
45
src/cpu/o3/dyn_inst.hh
Normal 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__
|
||||
@@ -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
Reference in New Issue
Block a user