Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/o3-merge/newmem --HG-- extra : convert_revision : 88fa7ae5cc32be068787ee381fae9d8de0e9bd0f
This commit is contained in:
commit
2fa535f740
49 changed files with 1186 additions and 973 deletions
39
configs/common/Caches.py
Normal file
39
configs/common/Caches.py
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: Lisa Hsu
|
||||
|
||||
import m5
|
||||
from m5.objects import *
|
||||
|
||||
class L1Cache(BaseCache):
|
||||
assoc = 2
|
||||
block_size = 64
|
||||
latency = 1
|
||||
mshrs = 10
|
||||
tgts_per_mshr = 5
|
||||
protocol = CoherenceProtocol(protocol='moesi')
|
||||
|
60
configs/common/Options.py
Normal file
60
configs/common/Options.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
# 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: Lisa Hsu
|
||||
|
||||
# system options
|
||||
parser.add_option("-d", "--detailed", action="store_true")
|
||||
parser.add_option("-t", "--timing", action="store_true")
|
||||
parser.add_option("-n", "--num_cpus", type="int", default=1)
|
||||
parser.add_option("--caches", action="store_true")
|
||||
|
||||
# Run duration options
|
||||
parser.add_option("-m", "--maxtick", type="int")
|
||||
parser.add_option("--maxtime", type="float")
|
||||
|
||||
# Checkpointing options
|
||||
###Note that performing checkpointing via python script files will override
|
||||
###checkpoint instructions built into binaries.
|
||||
parser.add_option("--take_checkpoints", action="store", type="string",
|
||||
help="<M,N> will take checkpoint at cycle M and every N cycles \
|
||||
thereafter")
|
||||
parser.add_option("--max_checkpoints", action="store", type="int",
|
||||
help="the maximum number of checkpoints to drop",
|
||||
default=5)
|
||||
parser.add_option("--checkpoint_dir", action="store", type="string",
|
||||
help="Place all checkpoints in this absolute directory")
|
||||
parser.add_option("-r", "--checkpoint_restore", action="store", type="int",
|
||||
help="restore from checkpoint <N>")
|
||||
|
||||
# CPU Switching - default switch model goes from a checkpoint
|
||||
# to a timing simple CPU with caches to warm up, then to detailed CPU for
|
||||
# data measurement
|
||||
parser.add_option("-s", "--standard_switch", action="store_true",
|
||||
help="switch from timing CPU to Detailed CPU")
|
||||
parser.add_option("-w", "--warmup", action="store", type="int",
|
||||
help="if -s, then this is the warmup period. else, this is ignored",
|
||||
default=5000000000)
|
177
configs/common/Simulation.py
Normal file
177
configs/common/Simulation.py
Normal file
|
@ -0,0 +1,177 @@
|
|||
# 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: Lisa Hsu
|
||||
|
||||
from os import getcwd
|
||||
import m5
|
||||
from m5.objects import *
|
||||
m5.AddToPath('../common')
|
||||
from Caches import L1Cache
|
||||
|
||||
def run(options, root, testsys):
|
||||
if options.maxtick:
|
||||
maxtick = options.maxtick
|
||||
elif options.maxtime:
|
||||
simtime = int(options.maxtime * root.clock.value)
|
||||
print "simulating for: ", simtime
|
||||
maxtick = simtime
|
||||
else:
|
||||
maxtick = -1
|
||||
|
||||
if options.checkpoint_dir:
|
||||
cptdir = options.checkpoint_dir
|
||||
else:
|
||||
cptdir = getcwd()
|
||||
|
||||
np = options.num_cpus
|
||||
max_checkpoints = options.max_checkpoints
|
||||
|
||||
if options.standard_switch:
|
||||
switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
|
||||
for i in xrange(np)]
|
||||
switch_cpus1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i))
|
||||
for i in xrange(np)]
|
||||
for i in xrange(np):
|
||||
switch_cpus[i].system = testsys
|
||||
switch_cpus1[i].system = testsys
|
||||
if not m5.build_env['FULL_SYSTEM']:
|
||||
switch_cpus[i].workload = testsys.cpu[i].workload
|
||||
switch_cpus1[i].workload = testsys.cpu[i].workload
|
||||
switch_cpus[i].clock = testsys.cpu[0].clock
|
||||
switch_cpus1[i].clock = testsys.cpu[0].clock
|
||||
if options.caches:
|
||||
switch_cpus[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||
L1Cache(size = '64kB'))
|
||||
|
||||
switch_cpus[i].mem = testsys.physmem
|
||||
switch_cpus1[i].mem = testsys.physmem
|
||||
switch_cpus[i].connectMemPorts(testsys.membus)
|
||||
root.switch_cpus = switch_cpus
|
||||
root.switch_cpus1 = switch_cpus1
|
||||
switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
|
||||
switch_cpu_list1 = [(switch_cpus[i], switch_cpus1[i]) for i in xrange(np)]
|
||||
|
||||
m5.instantiate(root)
|
||||
|
||||
if options.checkpoint_restore:
|
||||
from os.path import isdir
|
||||
from os import listdir
|
||||
import re
|
||||
|
||||
if not isdir(cptdir):
|
||||
m5.panic("checkpoint dir %s does not exist!" % cptdir)
|
||||
|
||||
dirs = listdir(cptdir)
|
||||
expr = re.compile('cpt.([0-9]*)')
|
||||
cpts = []
|
||||
for dir in dirs:
|
||||
match = expr.match(dir)
|
||||
if match:
|
||||
cpts.append(match.group(1))
|
||||
|
||||
cpts.sort(lambda a,b: cmp(long(a), long(b)))
|
||||
|
||||
cpt_num = options.checkpoint_restore
|
||||
|
||||
if cpt_num > len(cpts):
|
||||
m5.panic('Checkpoint %d not found' % cpt_num)
|
||||
|
||||
m5.restoreCheckpoint(root,
|
||||
"/".join([cptdir, "cpt.%s" % cpts[cpt_num - 1]]))
|
||||
|
||||
if options.standard_switch:
|
||||
exit_event = m5.simulate(10000)
|
||||
|
||||
## when you change to Timing (or Atomic), you halt the system given
|
||||
## as argument. When you are finished with the system changes
|
||||
## (including switchCpus), you must resume the system manually.
|
||||
## You DON'T need to resume after just switching CPUs if you haven't
|
||||
## changed anything on the system level.
|
||||
|
||||
m5.changeToTiming(testsys)
|
||||
m5.switchCpus(switch_cpu_list)
|
||||
m5.resume(testsys)
|
||||
|
||||
exit_event = m5.simulate(options.warmup)
|
||||
m5.switchCpus(switch_cpu_list1)
|
||||
|
||||
num_checkpoints = 0
|
||||
exit_cause = ''
|
||||
|
||||
## Checkpoints being taken via the command line at <when> and at subsequent
|
||||
## periods of <period>. Checkpoint instructions received from the benchmark running
|
||||
## are ignored and skipped in favor of command line checkpoint instructions.
|
||||
if options.take_checkpoints:
|
||||
[when, period] = options.take_checkpoints.split(",", 1)
|
||||
when = int(when)
|
||||
period = int(period)
|
||||
|
||||
exit_event = m5.simulate(when)
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
exit_event = m5.simulate(when - m5.curTick())
|
||||
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
|
||||
num_checkpoints += 1
|
||||
|
||||
sim_ticks = when
|
||||
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
|
||||
while num_checkpoints < max_checkpoints:
|
||||
if (sim_ticks + period) > maxtick and maxtick != -1:
|
||||
exit_event = m5.simulate(maxtick - sim_ticks)
|
||||
exit_cause = exit_event.getCause()
|
||||
break
|
||||
else:
|
||||
exit_event = m5.simulate(period)
|
||||
sim_ticks += period
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
exit_event = m5.simulate(sim_ticks - m5.curTick())
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
|
||||
num_checkpoints += 1
|
||||
|
||||
else: #no checkpoints being taken via this script
|
||||
exit_event = m5.simulate(maxtick)
|
||||
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
m5.checkpoint(root, "/".join([cptdir,"cpt.%d"]))
|
||||
num_checkpoints += 1
|
||||
if num_checkpoints == max_checkpoints:
|
||||
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
|
||||
break
|
||||
|
||||
if maxtick == -1:
|
||||
exit_event = m5.simulate(maxtick)
|
||||
else:
|
||||
exit_event = m5.simulate(maxtick - m5.curTick())
|
||||
|
||||
exit_cause = exit_event.getCause()
|
||||
|
||||
if exit_cause == '':
|
||||
exit_cause = exit_event.getCause()
|
||||
print 'Exiting @ cycle', m5.curTick(), 'because ', exit_cause
|
||||
|
|
@ -34,10 +34,16 @@ m5.AddToPath('../common')
|
|||
from FSConfig import *
|
||||
from SysPaths import *
|
||||
from Benchmarks import *
|
||||
import Simulation
|
||||
from Caches import *
|
||||
|
||||
if not m5.build_env['FULL_SYSTEM']:
|
||||
m5.panic("This script requires full-system mode (ALPHA_FS).")
|
||||
|
||||
# Get paths we might need. It's expected this file is in m5/configs/example.
|
||||
config_path = os.path.dirname(os.path.abspath(__file__))
|
||||
config_root = os.path.dirname(config_path)
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
# Benchmark options
|
||||
|
@ -48,40 +54,12 @@ parser.add_option("-b", "--benchmark", action="store", type="string",
|
|||
help="Specify the benchmark to run. Available benchmarks: %s"\
|
||||
% DefinedBenchmarks)
|
||||
|
||||
# system options
|
||||
parser.add_option("-d", "--detailed", action="store_true")
|
||||
parser.add_option("-t", "--timing", action="store_true")
|
||||
parser.add_option("-n", "--num_cpus", type="int", default=1)
|
||||
parser.add_option("--caches", action="store_true")
|
||||
|
||||
# Run duration options
|
||||
parser.add_option("-m", "--maxtick", type="int")
|
||||
parser.add_option("--maxtime", type="float")
|
||||
|
||||
# Metafile options
|
||||
parser.add_option("--etherdump", action="store", type="string", dest="etherdump",
|
||||
help="Specify the filename to dump a pcap capture of the" \
|
||||
"ethernet traffic")
|
||||
|
||||
# Checkpointing options
|
||||
###Note that performing checkpointing via python script files will override
|
||||
###checkpoint instructions built into binaries.
|
||||
parser.add_option("--take_checkpoints", action="store", type="string",
|
||||
help="<M,N> will take checkpoint at cycle M and every N cycles \
|
||||
thereafter")
|
||||
parser.add_option("--max_checkpoints", action="store", type="int",
|
||||
help="the maximum number of checkpoints to drop",
|
||||
default=5)
|
||||
parser.add_option("--checkpoint_dir", action="store", type="string",
|
||||
help="Place all checkpoints in this absolute directory")
|
||||
parser.add_option("-r", "--checkpoint_restore", action="store", type="int",
|
||||
help="restore from checkpoint <N>")
|
||||
|
||||
# CPU Switching - default switch model goes from a checkpoint
|
||||
# to a timing simple CPU with caches to warm up, then to detailed CPU for
|
||||
# data measurement
|
||||
parser.add_option("-s", "--standard_switch", action="store_true",
|
||||
help="switch from one cpu mode to another")
|
||||
execfile(os.path.join(config_root, "common", "Options.py"))
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
|
@ -89,14 +67,6 @@ if args:
|
|||
print "Error: script doesn't take any positional arguments"
|
||||
sys.exit(1)
|
||||
|
||||
class MyCache(BaseCache):
|
||||
assoc = 2
|
||||
block_size = 64
|
||||
latency = 1
|
||||
mshrs = 10
|
||||
tgts_per_mshr = 5
|
||||
protocol = CoherenceProtocol(protocol='moesi')
|
||||
|
||||
# driver system CPU is always simple... note this is an assignment of
|
||||
# a class, not an instance.
|
||||
DriveCPUClass = AtomicSimpleCPU
|
||||
|
@ -134,8 +104,8 @@ np = options.num_cpus
|
|||
test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)]
|
||||
for i in xrange(np):
|
||||
if options.caches and not options.standard_switch:
|
||||
test_sys.cpu[i].addPrivateSplitL1Caches(MyCache(size = '32kB'),
|
||||
MyCache(size = '64kB'))
|
||||
test_sys.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||
L1Cache(size = '64kB'))
|
||||
test_sys.cpu[i].connectMemPorts(test_sys.membus)
|
||||
test_sys.cpu[i].mem = test_sys.physmem
|
||||
|
||||
|
@ -151,129 +121,4 @@ else:
|
|||
print "Error I don't know how to create more than 2 systems."
|
||||
sys.exit(1)
|
||||
|
||||
if options.standard_switch:
|
||||
switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i)) for i in xrange(np)]
|
||||
switch_cpus1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i)) for i in xrange(np)]
|
||||
for i in xrange(np):
|
||||
switch_cpus[i].system = test_sys
|
||||
switch_cpus1[i].system = test_sys
|
||||
switch_cpus[i].clock = TestCPUClass.clock
|
||||
switch_cpus1[i].clock = TestCPUClass.clock
|
||||
if options.caches:
|
||||
switch_cpus[i].addPrivateSplitL1Caches(MyCache(size = '32kB'),
|
||||
MyCache(size = '64kB'))
|
||||
|
||||
switch_cpus[i].mem = test_sys.physmem
|
||||
switch_cpus1[i].mem = test_sys.physmem
|
||||
switch_cpus[i].connectMemPorts(test_sys.membus)
|
||||
root.switch_cpus = switch_cpus
|
||||
root.switch_cpus1 = switch_cpus1
|
||||
switch_cpu_list = [(test_sys.cpu[i], switch_cpus[i]) for i in xrange(np)]
|
||||
switch_cpu_list1 = [(switch_cpus[i], switch_cpus1[i]) for i in xrange(np)]
|
||||
|
||||
m5.instantiate(root)
|
||||
|
||||
if options.checkpoint_dir:
|
||||
cptdir = options.checkpoint_dir
|
||||
else:
|
||||
cptdir = os.getcwd()
|
||||
|
||||
if options.checkpoint_restore:
|
||||
from os.path import isdir
|
||||
from os import listdir, getcwd
|
||||
import re
|
||||
|
||||
if not isdir(cptdir):
|
||||
m5.panic("checkpoint dir %s does not exist!" % cptdir)
|
||||
|
||||
dirs = listdir(cptdir)
|
||||
expr = re.compile('cpt.([0-9]*)')
|
||||
cpts = []
|
||||
for dir in dirs:
|
||||
match = expr.match(dir)
|
||||
if match:
|
||||
cpts.append(match.group(1))
|
||||
|
||||
cpts.sort(lambda a,b: cmp(long(a), long(b)))
|
||||
|
||||
if options.checkpoint_restore > len(cpts):
|
||||
m5.panic('Checkpoint %d not found' % options.checkpoint_restore)
|
||||
|
||||
m5.restoreCheckpoint(root, "/".join([cptdir, "cpt.%s" % cpts[options.checkpoint_restore - 1]]))
|
||||
|
||||
if options.standard_switch:
|
||||
exit_event = m5.simulate(1000)
|
||||
## when you change to Timing (or Atomic), you halt the system given
|
||||
## as argument. When you are finished with the system changes
|
||||
## (including switchCpus), you must resume the system manually.
|
||||
## You DON'T need to resume after just switching CPUs if you haven't
|
||||
## changed anything on the system level.
|
||||
m5.changeToTiming(test_sys)
|
||||
m5.switchCpus(switch_cpu_list)
|
||||
m5.resume(test_sys)
|
||||
|
||||
exit_event = m5.simulate(500000000000)
|
||||
m5.switchCpus(switch_cpu_list1)
|
||||
|
||||
if options.maxtick:
|
||||
maxtick = options.maxtick
|
||||
elif options.maxtime:
|
||||
simtime = int(options.maxtime * root.clock.value)
|
||||
print "simulating for: ", simtime
|
||||
maxtick = simtime
|
||||
else:
|
||||
maxtick = -1
|
||||
|
||||
num_checkpoints = 0
|
||||
|
||||
exit_cause = ''
|
||||
|
||||
if options.take_checkpoints:
|
||||
[when, period] = options.take_checkpoints.split(",", 1)
|
||||
when = int(when)
|
||||
period = int(period)
|
||||
|
||||
exit_event = m5.simulate(when)
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
exit_event = m5.simulate(when - m5.curTick())
|
||||
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, cptdir + "cpt.%d")
|
||||
num_checkpoints += 1
|
||||
|
||||
sim_ticks = when
|
||||
exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints
|
||||
while num_checkpoints < options.max_checkpoints:
|
||||
if (sim_ticks + period) > maxtick and maxtick != -1:
|
||||
exit_event = m5.simulate(maxtick - sim_ticks)
|
||||
exit_cause = exit_event.getCause()
|
||||
break
|
||||
else:
|
||||
exit_event = m5.simulate(period)
|
||||
sim_ticks += period
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
exit_event = m5.simulate(period - m5.curTick())
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, cptdir + "cpt.%d")
|
||||
num_checkpoints += 1
|
||||
|
||||
else: #no checkpoints being taken via this script
|
||||
exit_event = m5.simulate(maxtick)
|
||||
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
m5.checkpoint(root, cptdir + "cpt.%d")
|
||||
num_checkpoints += 1
|
||||
if num_checkpoints == options.max_checkpoints:
|
||||
exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints
|
||||
break
|
||||
|
||||
if maxtick == -1:
|
||||
exit_event = m5.simulate(maxtick)
|
||||
else:
|
||||
exit_event = m5.simulate(maxtick - m5.curTick())
|
||||
|
||||
exit_cause = exit_event.getCause()
|
||||
|
||||
if exit_cause == '':
|
||||
exit_cause = exit_event.getCause()
|
||||
print 'Exiting @ cycle', m5.curTick(), 'because ', exit_cause
|
||||
Simulation.run(options, root, test_sys)
|
||||
|
|
|
@ -34,12 +34,23 @@ import m5
|
|||
from m5.objects import *
|
||||
import os, optparse, sys
|
||||
m5.AddToPath('../common')
|
||||
import Simulation
|
||||
from Caches import *
|
||||
|
||||
# Get paths we might need. It's expected this file is in m5/configs/example.
|
||||
config_path = os.path.dirname(os.path.abspath(__file__))
|
||||
config_root = os.path.dirname(config_path)
|
||||
m5_root = os.path.dirname(config_root)
|
||||
print m5_root
|
||||
print config_path
|
||||
print config_root
|
||||
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
# Benchmark options
|
||||
parser.add_option("-c", "--cmd",
|
||||
default="../../tests/test-progs/hello/bin/alpha/linux/hello",
|
||||
default=os.path.join(m5_root, "tests/test-progs/hello/bin/alpha/linux/hello"),
|
||||
help="The binary to run in syscall emulation mode.")
|
||||
parser.add_option("-o", "--options", default="",
|
||||
help="The options to pass to the binary, use \" \" around the entire\
|
||||
|
@ -47,34 +58,7 @@ parser.add_option("-o", "--options", default="",
|
|||
parser.add_option("-i", "--input", default="",
|
||||
help="A file of input to give to the binary.")
|
||||
|
||||
# System options
|
||||
parser.add_option("-d", "--detailed", action="store_true")
|
||||
parser.add_option("-t", "--timing", action="store_true")
|
||||
parser.add_option("--caches", action="store_true")
|
||||
|
||||
# Run duration options
|
||||
parser.add_option("-m", "--maxtick", type="int")
|
||||
parser.add_option("--maxtime", type="float")
|
||||
|
||||
#Checkpointing options
|
||||
###Note that performing checkpointing via python script files will override
|
||||
###checkpoint instructions built into binaries.
|
||||
parser.add_option("--take_checkpoints", action="store", type="string",
|
||||
help="<M,N> will take checkpoint at cycle M and every N cycles \
|
||||
thereafter")
|
||||
parser.add_option("--max_checkpoints", action="store", type="int",
|
||||
help="the maximum number of checkpoints to drop",
|
||||
default=5)
|
||||
parser.add_option("--checkpoint_dir", action="store", type="string",
|
||||
help="Place all checkpoints in this absolute directory")
|
||||
parser.add_option("-r", "--checkpoint_restore", action="store", type="int",
|
||||
help="restore from checkpoint <N>")
|
||||
|
||||
#CPU Switching - default switch model generally goes from a checkpoint
|
||||
#to a timing simple CPU with caches to warm up, then to detailed CPU for
|
||||
#data measurement
|
||||
parser.add_option("-s", "--standard_switch", action="store_true",
|
||||
help="switch from one cpu mode to another")
|
||||
execfile(os.path.join(config_root, "common", "Options.py"))
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
|
@ -82,13 +66,6 @@ if args:
|
|||
print "Error: script doesn't take any positional arguments"
|
||||
sys.exit(1)
|
||||
|
||||
class MyCache(BaseCache):
|
||||
assoc = 2
|
||||
block_size = 64
|
||||
latency = 1
|
||||
mshrs = 10
|
||||
tgts_per_mshr = 5
|
||||
|
||||
process = LiveProcess()
|
||||
process.executable = options.cmd
|
||||
process.cmd = options.cmd + " " + options.options
|
||||
|
@ -117,159 +94,33 @@ if options.detailed:
|
|||
|
||||
|
||||
if options.timing:
|
||||
cpu = TimingSimpleCPU()
|
||||
CPUClass = TimingSimpleCPU
|
||||
test_mem_mode = 'timing'
|
||||
elif options.detailed:
|
||||
cpu = DerivO3CPU()
|
||||
CPUClass = DerivO3CPU
|
||||
test_mem_mode = 'timing'
|
||||
else:
|
||||
cpu = AtomicSimpleCPU()
|
||||
CPUClass = AtomicSimpleCPU
|
||||
test_mem_mode = 'atomic'
|
||||
|
||||
cpu.workload = process
|
||||
cpu.cpu_id = 0
|
||||
CPUClass.clock = '2GHz'
|
||||
|
||||
system = System(cpu = cpu,
|
||||
np = options.num_cpus
|
||||
|
||||
system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)],
|
||||
physmem = PhysicalMemory(range=AddrRange("512MB")),
|
||||
membus = Bus())
|
||||
membus = Bus(), mem_mode = test_mem_mode)
|
||||
|
||||
system.physmem.port = system.membus.port
|
||||
system.cpu.connectMemPorts(system.membus)
|
||||
system.cpu.mem = system.physmem
|
||||
system.cpu.clock = '2GHz'
|
||||
if options.caches and not options.standard_switch:
|
||||
system.cpu.addPrivateSplitL1Caches(MyCache(size = '32kB'),
|
||||
MyCache(size = '64kB'))
|
||||
|
||||
for i in xrange(np):
|
||||
if options.caches and not options.standard_switch:
|
||||
system.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
|
||||
L1Cache(size = '64kB'))
|
||||
system.cpu[i].connectMemPorts(system.membus)
|
||||
system.cpu[i].mem = system.physmem
|
||||
system.cpu[i].workload = process
|
||||
|
||||
root = Root(system = system)
|
||||
|
||||
if options.timing or options.detailed:
|
||||
root.system.mem_mode = 'timing'
|
||||
|
||||
if options.standard_switch:
|
||||
switch_cpu = TimingSimpleCPU(defer_registration=True, cpu_id=1)
|
||||
switch_cpu1 = DerivO3CPU(defer_registration=True, cpu_id=2)
|
||||
switch_cpu.system = system
|
||||
switch_cpu1.system = system
|
||||
switch_cpu.clock = cpu.clock
|
||||
switch_cpu1.clock = cpu.clock
|
||||
if options.caches:
|
||||
switch_cpu.addPrivateSplitL1Caches(MyCache(size = '32kB'),
|
||||
MyCache(size = '64kB'))
|
||||
|
||||
switch_cpu.workload = process
|
||||
switch_cpu1.workload = process
|
||||
switch_cpu.mem = system.physmem
|
||||
switch_cpu1.mem = system.physmem
|
||||
switch_cpu.connectMemPorts(system.membus)
|
||||
root.switch_cpu = switch_cpu
|
||||
root.switch_cpu1 = switch_cpu1
|
||||
switch_cpu_list = [(system.cpu, switch_cpu)]
|
||||
switch_cpu_list1 = [(switch_cpu, switch_cpu1)]
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
|
||||
if options.checkpoint_dir:
|
||||
cptdir = options.checkpoint_dir
|
||||
else:
|
||||
cptdir = getcwd()
|
||||
|
||||
if options.checkpoint_restore:
|
||||
from os.path import isdir
|
||||
from os import listdir, getcwd
|
||||
import re
|
||||
|
||||
if not isdir(cptdir):
|
||||
m5.panic("checkpoint dir %s does not exist!" % cptdir)
|
||||
|
||||
dirs = listdir(cptdir)
|
||||
expr = re.compile('cpt.([0-9]*)')
|
||||
cpts = []
|
||||
for dir in dirs:
|
||||
match = expr.match(dir)
|
||||
if match:
|
||||
cpts.append(match.group(1))
|
||||
|
||||
cpts.sort(lambda a,b: cmp(long(a), long(b)))
|
||||
|
||||
if options.checkpoint_restore > len(cpts):
|
||||
m5.panic('Checkpoint %d not found' % options.checkpoint_restore)
|
||||
|
||||
print "restoring checkpoint from ","/".join([cptdir, "cpt.%s" % cpts[options.checkpoint_restore - 1]])
|
||||
m5.restoreCheckpoint(root, "/".join([cptdir, "cpt.%s" % cpts[options.checkpoint_restore - 1]]))
|
||||
|
||||
if options.standard_switch:
|
||||
exit_event = m5.simulate(10000)
|
||||
## when you change to Timing (or Atomic), you halt the system given
|
||||
## as argument. When you are finished with the system changes
|
||||
## (including switchCpus), you must resume the system manually.
|
||||
## You DON'T need to resume after just switching CPUs if you haven't
|
||||
## changed anything on the system level.
|
||||
m5.changeToTiming(system)
|
||||
m5.switchCpus(switch_cpu_list)
|
||||
m5.resume(system)
|
||||
|
||||
exit_event = m5.simulate(500000000000)
|
||||
m5.switchCpus(switch_cpu_list1)
|
||||
|
||||
if options.maxtick:
|
||||
maxtick = options.maxtick
|
||||
elif options.maxtime:
|
||||
simtime = int(options.maxtime * root.clock.value)
|
||||
print "simulating for: ", simtime
|
||||
maxtick = simtime
|
||||
else:
|
||||
maxtick = -1
|
||||
|
||||
num_checkpoints = 0
|
||||
|
||||
exit_cause = ''
|
||||
|
||||
if options.take_checkpoints:
|
||||
[when, period] = options.take_checkpoints.split(",", 1)
|
||||
when = int(when)
|
||||
period = int(period)
|
||||
|
||||
exit_event = m5.simulate(when)
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
exit_event = m5.simulate(when - m5.curTick())
|
||||
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, cptdir + "cpt.%d")
|
||||
num_checkpoints += 1
|
||||
|
||||
sim_ticks = when
|
||||
exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints
|
||||
while num_checkpoints < options.max_checkpoints:
|
||||
if (sim_ticks + period) > maxtick and maxtick != -1:
|
||||
exit_event = m5.simulate(maxtick - sim_ticks)
|
||||
exit_cause = exit_event.getCause()
|
||||
break
|
||||
else:
|
||||
exit_event = m5.simulate(period)
|
||||
sim_ticks += period
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
exit_event = m5.simulate(period - m5.curTick())
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, cptdir + "cpt.%d")
|
||||
num_checkpoints += 1
|
||||
|
||||
else: #no checkpoints being taken via this script
|
||||
exit_event = m5.simulate(maxtick)
|
||||
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
m5.checkpoint(root, cptdir + "cpt.%d")
|
||||
num_checkpoints += 1
|
||||
if num_checkpoints == options.max_checkpoints:
|
||||
exit_cause = "maximum %d checkpoints dropped" % options.max_checkpoints
|
||||
break
|
||||
|
||||
if maxtick == -1:
|
||||
exit_event = m5.simulate(maxtick)
|
||||
else:
|
||||
exit_event = m5.simulate(maxtick - m5.curTick())
|
||||
|
||||
exit_cause = exit_event.getCause()
|
||||
|
||||
if exit_cause == '':
|
||||
exit_cause = exit_event.getCause()
|
||||
print 'Exiting @ cycle', m5.curTick(), 'because ', exit_cause
|
||||
|
||||
|
||||
Simulation.run(options, root, system)
|
||||
|
|
|
@ -220,7 +220,6 @@ full_system_sources = Split('''
|
|||
dev/etherlink.cc
|
||||
dev/etherpkt.cc
|
||||
dev/ethertap.cc
|
||||
dev/i8254xGBe.cc
|
||||
dev/ide_ctrl.cc
|
||||
dev/ide_disk.cc
|
||||
dev/io_device.cc
|
||||
|
@ -253,6 +252,7 @@ full_system_sources = Split('''
|
|||
sim/pseudo_inst.cc
|
||||
''')
|
||||
#dev/sinic.cc
|
||||
#dev/i8254xGBe.cc
|
||||
|
||||
|
||||
if env['TARGET_ISA'] == 'alpha':
|
||||
|
|
|
@ -1316,7 +1316,7 @@ class ControlRegOperand(Operand):
|
|||
def makeWrite(self):
|
||||
if (self.ctype == 'float' or self.ctype == 'double'):
|
||||
error(0, 'Attempt to write control register as FP')
|
||||
wb = 'xc->setMiscReg(%s, %s);\n' % (self.reg_spec, self.base_name)
|
||||
wb = 'xc->setMiscRegWithEffect(%s, %s);\n' % (self.reg_spec, self.base_name)
|
||||
wb += 'if (traceData) { traceData->setData(%s); }' % \
|
||||
self.base_name
|
||||
return wb
|
||||
|
|
|
@ -29,15 +29,22 @@
|
|||
* Kevin Lim
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "arch/sparc/faults.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/process.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#if !FULL_SYSTEM
|
||||
#include "sim/process.hh"
|
||||
#include "mem/page_table.hh"
|
||||
#include "sim/process.hh"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace SparcISA
|
||||
{
|
||||
|
||||
|
@ -229,6 +236,121 @@ FaultPriority PageTableFault::_priority = 0;
|
|||
FaultStat PageTableFault::_count;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This sets everything up for a normal trap except for actually jumping to
|
||||
* the handler. It will need to be expanded to include the state machine in
|
||||
* the manual. Right now it assumes that traps will always be to the
|
||||
* privileged level.
|
||||
*/
|
||||
|
||||
void doNormalFault(ThreadContext *tc, TrapType tt)
|
||||
{
|
||||
uint64_t TL = tc->readMiscReg(MISCREG_TL);
|
||||
uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE);
|
||||
uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE);
|
||||
uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
|
||||
uint64_t CCR = tc->readMiscReg(MISCREG_CCR);
|
||||
uint64_t ASI = tc->readMiscReg(MISCREG_ASI);
|
||||
uint64_t CWP = tc->readMiscReg(MISCREG_CWP);
|
||||
uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
|
||||
uint64_t GL = tc->readMiscReg(MISCREG_GL);
|
||||
uint64_t PC = tc->readPC();
|
||||
uint64_t NPC = tc->readNextPC();
|
||||
|
||||
//Increment the trap level
|
||||
TL++;
|
||||
tc->setMiscReg(MISCREG_TL, TL);
|
||||
|
||||
//Save off state
|
||||
|
||||
//set TSTATE.gl to gl
|
||||
replaceBits(TSTATE, 42, 40, GL);
|
||||
//set TSTATE.ccr to ccr
|
||||
replaceBits(TSTATE, 39, 32, CCR);
|
||||
//set TSTATE.asi to asi
|
||||
replaceBits(TSTATE, 31, 24, ASI);
|
||||
//set TSTATE.pstate to pstate
|
||||
replaceBits(TSTATE, 20, 8, PSTATE);
|
||||
//set TSTATE.cwp to cwp
|
||||
replaceBits(TSTATE, 4, 0, CWP);
|
||||
|
||||
//Write back TSTATE
|
||||
tc->setMiscReg(MISCREG_TSTATE, TSTATE);
|
||||
|
||||
//set TPC to PC
|
||||
tc->setMiscReg(MISCREG_TPC, PC);
|
||||
//set TNPC to NPC
|
||||
tc->setMiscReg(MISCREG_TNPC, NPC);
|
||||
|
||||
//set HTSTATE.hpstate to hpstate
|
||||
tc->setMiscReg(MISCREG_HTSTATE, HPSTATE);
|
||||
|
||||
//TT = trap type;
|
||||
tc->setMiscReg(MISCREG_TT, tt);
|
||||
|
||||
//Update the global register level
|
||||
if(1/*We're delivering the trap in priveleged mode*/)
|
||||
tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL));
|
||||
else
|
||||
tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL));
|
||||
|
||||
//PSTATE.mm is unchanged
|
||||
//PSTATE.pef = whether or not an fpu is present
|
||||
//XXX We'll say there's one present, even though there aren't
|
||||
//implementations for a decent number of the instructions
|
||||
PSTATE |= (1 << 4);
|
||||
//PSTATE.am = 0
|
||||
PSTATE &= ~(1 << 3);
|
||||
if(1/*We're delivering the trap in priveleged mode*/)
|
||||
{
|
||||
//PSTATE.priv = 1
|
||||
PSTATE |= (1 << 2);
|
||||
//PSTATE.cle = PSTATE.tle
|
||||
replaceBits(PSTATE, 9, 9, PSTATE >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
//PSTATE.priv = 0
|
||||
PSTATE &= ~(1 << 2);
|
||||
//PSTATE.cle = 0
|
||||
PSTATE &= ~(1 << 9);
|
||||
}
|
||||
//PSTATE.ie = 0
|
||||
PSTATE &= ~(1 << 1);
|
||||
//PSTATE.tle is unchanged
|
||||
//PSTATE.tct = 0
|
||||
//XXX Where exactly is this field?
|
||||
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
|
||||
|
||||
if(0/*We're delivering the trap in hyperprivileged mode*/)
|
||||
{
|
||||
//HPSTATE.red = 0
|
||||
HPSTATE &= ~(1 << 5);
|
||||
//HPSTATE.hpriv = 1
|
||||
HPSTATE |= (1 << 2);
|
||||
//HPSTATE.ibe = 0
|
||||
HPSTATE &= ~(1 << 10);
|
||||
//HPSTATE.tlz is unchanged
|
||||
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
|
||||
}
|
||||
|
||||
bool changedCWP = true;
|
||||
if(tt == 0x24)
|
||||
CWP++;
|
||||
else if(0x80 <= tt && tt <= 0xbf)
|
||||
CWP += (CANSAVE + 2);
|
||||
else if(0xc0 <= tt && tt <= 0xff)
|
||||
CWP--;
|
||||
else
|
||||
changedCWP = false;
|
||||
|
||||
if(changedCWP)
|
||||
{
|
||||
CWP = (CWP + NWindows) % NWindows;
|
||||
tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
|
||||
}
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
|
||||
void SparcFault::invoke(ThreadContext * tc)
|
||||
|
@ -263,6 +385,40 @@ void TrapInstruction::invoke(ThreadContext * tc)
|
|||
// Should be handled in ISA.
|
||||
}
|
||||
|
||||
void SpillNNormal::invoke(ThreadContext *tc)
|
||||
{
|
||||
doNormalFault(tc, trapType());
|
||||
|
||||
Process *p = tc->getProcessPtr();
|
||||
|
||||
//This will only work in faults from a SparcLiveProcess
|
||||
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
|
||||
assert(lp);
|
||||
|
||||
//Then adjust the PC and NPC
|
||||
Addr spillStart = lp->readSpillStart();
|
||||
tc->setPC(spillStart);
|
||||
tc->setNextPC(spillStart + sizeof(MachInst));
|
||||
tc->setNextNPC(spillStart + 2*sizeof(MachInst));
|
||||
}
|
||||
|
||||
void FillNNormal::invoke(ThreadContext *tc)
|
||||
{
|
||||
doNormalFault(tc, trapType());
|
||||
|
||||
Process * p = tc->getProcessPtr();
|
||||
|
||||
//This will only work in faults from a SparcLiveProcess
|
||||
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
|
||||
assert(lp);
|
||||
|
||||
//The adjust the PC and NPC
|
||||
Addr fillStart = lp->readFillStart();
|
||||
tc->setPC(fillStart);
|
||||
tc->setNextPC(fillStart + sizeof(MachInst));
|
||||
tc->setNextNPC(fillStart + 2*sizeof(MachInst));
|
||||
}
|
||||
|
||||
void PageTableFault::invoke(ThreadContext *tc)
|
||||
{
|
||||
Process *p = tc->getProcessPtr();
|
||||
|
@ -282,6 +438,7 @@ void PageTableFault::invoke(ThreadContext *tc)
|
|||
FaultBase::invoke(tc);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace SparcISA
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
namespace SparcISA
|
||||
{
|
||||
|
||||
typedef const uint32_t TrapType;
|
||||
typedef const uint32_t FaultPriority;
|
||||
typedef uint32_t TrapType;
|
||||
typedef uint32_t FaultPriority;
|
||||
|
||||
class SparcFault : public FaultBase
|
||||
{
|
||||
|
@ -547,6 +547,7 @@ class SpillNNormal : public EnumeratedFault
|
|||
FaultName name() {return _name;}
|
||||
FaultPriority priority() {return _priority;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class SpillNOther : public EnumeratedFault
|
||||
|
@ -577,6 +578,7 @@ class FillNNormal : public EnumeratedFault
|
|||
FaultName name() {return _name;}
|
||||
FaultPriority priority() {return _priority;}
|
||||
FaultStat & countStat() {return _count;}
|
||||
void invoke(ThreadContext * tc);
|
||||
};
|
||||
|
||||
class FillNOther : public EnumeratedFault
|
||||
|
|
|
@ -75,8 +75,14 @@ IntRegFile::IntRegFile()
|
|||
|
||||
IntReg IntRegFile::readReg(int intReg)
|
||||
{
|
||||
IntReg val =
|
||||
regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
|
||||
IntReg val;
|
||||
if(intReg < NumRegularIntRegs)
|
||||
val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
|
||||
else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs)
|
||||
val = microRegs[intReg];
|
||||
else
|
||||
panic("Tried to read non-existant integer register\n");
|
||||
|
||||
DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val);
|
||||
return val;
|
||||
}
|
||||
|
@ -86,7 +92,12 @@ Fault IntRegFile::setReg(int intReg, const IntReg &val)
|
|||
if(intReg)
|
||||
{
|
||||
DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
|
||||
regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
|
||||
if(intReg < NumRegularIntRegs)
|
||||
regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
|
||||
else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs)
|
||||
microRegs[intReg] = val;
|
||||
else
|
||||
panic("Tried to set non-existant integer register\n");
|
||||
}
|
||||
return NoFault;
|
||||
}
|
||||
|
@ -123,6 +134,7 @@ void IntRegFile::serialize(std::ostream &os)
|
|||
SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame);
|
||||
for(x = 0; x < 2 * NWindows; x++)
|
||||
SERIALIZE_ARRAY(regSegments[x], RegsPerFrame);
|
||||
SERIALIZE_ARRAY(microRegs, NumMicroIntRegs);
|
||||
}
|
||||
|
||||
void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
|
@ -132,4 +144,5 @@ void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame);
|
||||
for(unsigned int x = 0; x < 2 * NWindows; x++)
|
||||
UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame);
|
||||
UNSERIALIZE_ARRAY(microRegs, NumMicroIntRegs);
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace SparcISA
|
|||
|
||||
IntReg regGlobals[MaxGL][RegsPerFrame];
|
||||
IntReg regSegments[2 * NWindows][RegsPerFrame];
|
||||
IntReg microRegs[NumMicroIntRegs];
|
||||
|
||||
enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ def bitfield D16LO <13:0>;
|
|||
def bitfield DISP19 <18:0>;
|
||||
def bitfield DISP22 <21:0>;
|
||||
def bitfield DISP30 <29:0>;
|
||||
def bitfield FCN <29:26>;
|
||||
def bitfield FCN <29:25>;
|
||||
def bitfield I <13>;
|
||||
def bitfield IMM_ASI <12:5>;
|
||||
def bitfield IMM22 <21:0>;
|
||||
|
|
|
@ -357,13 +357,9 @@ decode OP default Unknown::unknown()
|
|||
}});
|
||||
}
|
||||
0x29: HPriv::rdhpr({{
|
||||
// XXX Need to protect with format that traps non-priv/priv
|
||||
// access
|
||||
Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault);
|
||||
}});
|
||||
0x2A: Priv::rdpr({{
|
||||
// XXX Need to protect with format that traps non-priv
|
||||
// access
|
||||
Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault);
|
||||
}});
|
||||
0x2B: BasicOperate::flushw({{
|
||||
|
@ -425,18 +421,34 @@ decode OP default Unknown::unknown()
|
|||
xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13);
|
||||
}});
|
||||
0x31: decode FCN {
|
||||
0x0: BasicOperate::saved({{/*Boogy Boogy*/}});
|
||||
0x1: BasicOperate::restored({{/*Boogy Boogy*/}});
|
||||
0x0: Priv::saved({{
|
||||
assert(Cansave < NWindows - 2);
|
||||
assert(Otherwin || Canrestore);
|
||||
Cansave = Cansave + 1;
|
||||
if(Otherwin == 0)
|
||||
Canrestore = Canrestore - 1;
|
||||
else
|
||||
Otherwin = Otherwin - 1;
|
||||
}});
|
||||
0x1: BasicOperate::restored({{
|
||||
assert(Cansave || Otherwin);
|
||||
assert(Canrestore < NWindows - 2);
|
||||
Canrestore = Canrestore + 1;
|
||||
if(Otherwin == 0)
|
||||
Cansave = Cansave - 1;
|
||||
else
|
||||
Otherwin = Otherwin - 1;
|
||||
}});
|
||||
}
|
||||
0x32: Priv::wrpr({{
|
||||
// XXX Need to protect with format that traps non-priv
|
||||
// access
|
||||
fault = xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
|
||||
xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
|
||||
}});
|
||||
0x33: HPriv::wrhpr({{
|
||||
// XXX Need to protect with format that traps non-priv/priv
|
||||
// access
|
||||
fault = xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
|
||||
xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
|
||||
}});
|
||||
0x34: decode OPF{
|
||||
format BasicOperate{
|
||||
|
@ -684,10 +696,6 @@ decode OP default Unknown::unknown()
|
|||
NNPC = target;
|
||||
if(fault == NoFault)
|
||||
{
|
||||
//CWP should be set directly so that it always happens
|
||||
//Also, this will allow writing to the new window and
|
||||
//reading from the old one
|
||||
Cwp = (Cwp - 1 + NWindows) % NWindows;
|
||||
if(Canrestore == 0)
|
||||
{
|
||||
if(Otherwin)
|
||||
|
@ -697,14 +705,17 @@ decode OP default Unknown::unknown()
|
|||
}
|
||||
else
|
||||
{
|
||||
Rd = Rs1 + Rs2_or_imm13;
|
||||
//CWP should be set directly so that it always happens
|
||||
//Also, this will allow writing to the new window and
|
||||
//reading from the old one
|
||||
Cwp = (Cwp - 1 + NWindows) % NWindows;
|
||||
Cansave = Cansave + 1;
|
||||
Canrestore = Canrestore - 1;
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
//are written in the new window as well.
|
||||
xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
|
||||
}
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
//are written in the new window as well.
|
||||
xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
|
||||
}
|
||||
}});
|
||||
0x3A: decode CC
|
||||
|
@ -747,11 +758,11 @@ decode OP default Unknown::unknown()
|
|||
fault = new SpillNOther(Wstate<5:3>);
|
||||
else
|
||||
fault = new SpillNNormal(Wstate<2:0>);
|
||||
Cwp = (Cwp + 2) % NWindows;
|
||||
//Cwp = (Cwp + 2) % NWindows;
|
||||
}
|
||||
else if(Cleanwin - Canrestore == 0)
|
||||
{
|
||||
Cwp = (Cwp + 1) % NWindows;
|
||||
//Cwp = (Cwp + 1) % NWindows;
|
||||
fault = new CleanWindow;
|
||||
}
|
||||
else
|
||||
|
@ -760,17 +771,13 @@ decode OP default Unknown::unknown()
|
|||
Rd = Rs1 + Rs2_or_imm13;
|
||||
Cansave = Cansave - 1;
|
||||
Canrestore = Canrestore + 1;
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
//are written in the new window as well.
|
||||
xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
|
||||
}
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
//are written in the new window as well.
|
||||
xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
|
||||
}});
|
||||
0x3D: restore({{
|
||||
//CWP should be set directly so that it always happens
|
||||
//Also, this will allow writing to the new window and
|
||||
//reading from the old one
|
||||
Cwp = (Cwp - 1 + NWindows) % NWindows;
|
||||
if(Canrestore == 0)
|
||||
{
|
||||
if(Otherwin)
|
||||
|
@ -780,14 +787,18 @@ decode OP default Unknown::unknown()
|
|||
}
|
||||
else
|
||||
{
|
||||
//CWP should be set directly so that it always happens
|
||||
//Also, this will allow writing to the new window and
|
||||
//reading from the old one
|
||||
Cwp = (Cwp - 1 + NWindows) % NWindows;
|
||||
Rd = Rs1 + Rs2_or_imm13;
|
||||
Cansave = Cansave + 1;
|
||||
Canrestore = Canrestore - 1;
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
//are written in the new window as well.
|
||||
xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
|
||||
}
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
//are written in the new window as well.
|
||||
xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
|
||||
}});
|
||||
0x3E: decode FCN {
|
||||
0x0: Priv::done({{
|
||||
|
@ -812,7 +823,7 @@ decode OP default Unknown::unknown()
|
|||
Ccr = Tstate<39:32>;
|
||||
Gl = Tstate<42:40>;
|
||||
NPC = Tpc;
|
||||
NNPC = Tnpc + 4;
|
||||
NNPC = Tnpc;
|
||||
Tl = Tl - 1;
|
||||
}});
|
||||
}
|
||||
|
@ -840,16 +851,15 @@ decode OP default Unknown::unknown()
|
|||
0x09: ldsb({{Rd = (int8_t)Mem.sb;}});
|
||||
0x0A: ldsh({{Rd = (int16_t)Mem.shw;}});
|
||||
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
|
||||
0x0D: ldstub({{
|
||||
Rd = Mem.ub;
|
||||
Mem.ub = 0xFF;
|
||||
}});
|
||||
}
|
||||
0x0D: LoadStore::ldstub(
|
||||
{{Rd = Mem.ub;}},
|
||||
{{Mem.ub = 0xFF;}});
|
||||
0x0E: Store::stx({{Mem.udw = Rd}});
|
||||
0x0F: LoadStore::swap(
|
||||
{{*temp = Rd.uw;
|
||||
{{uReg0 = Rd.uw;
|
||||
Rd.uw = Mem.uw;}},
|
||||
{{Mem.uw = *temp;}});
|
||||
{{Mem.uw = uReg0;}});
|
||||
format Load {
|
||||
0x10: lduwa({{Rd = Mem.uw;}});
|
||||
0x11: lduba({{Rd = Mem.ub;}});
|
||||
|
@ -877,9 +887,9 @@ decode OP default Unknown::unknown()
|
|||
{{Mem.ub = 0xFF}});
|
||||
0x1E: Store::stxa({{Mem.udw = Rd}});
|
||||
0x1F: LoadStore::swapa(
|
||||
{{*temp = Rd.uw;
|
||||
{{uReg0 = Rd.uw;
|
||||
Rd.uw = Mem.uw;}},
|
||||
{{Mem.uw = *temp;}});
|
||||
{{Mem.uw = uReg0;}});
|
||||
format Trap {
|
||||
0x20: Load::ldf({{Frd.uw = Mem.uw;}});
|
||||
0x21: decode X {
|
||||
|
@ -1062,19 +1072,21 @@ decode OP default Unknown::unknown()
|
|||
{{fault = new DataAccessException;}});
|
||||
}
|
||||
}
|
||||
0x3C: Cas::casa({{
|
||||
uint64_t val = Mem.uw;
|
||||
if(Rs2.uw == val)
|
||||
0x3C: Cas::casa(
|
||||
{{uReg0 = Mem.uw;}},
|
||||
{{if(Rs2.uw == uReg0)
|
||||
Mem.uw = Rd.uw;
|
||||
Rd.uw = val;
|
||||
}});
|
||||
else
|
||||
storeCond = false;
|
||||
Rd.uw = uReg0;}});
|
||||
0x3D: Nop::prefetcha({{ }});
|
||||
0x3E: Cas::casxa({{
|
||||
uint64_t val = Mem.udw;
|
||||
if(Rs2 == val)
|
||||
0x3E: Cas::casxa(
|
||||
{{uReg0 = Mem.udw;}},
|
||||
{{if(Rs2 == uReg0)
|
||||
Mem.udw = Rd;
|
||||
Rd = val;
|
||||
}});
|
||||
else
|
||||
storeCond = false;
|
||||
Rd = uReg0;}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,9 +42,6 @@
|
|||
//Include the memory formats
|
||||
##include "mem/mem.isa"
|
||||
|
||||
//Include the compare and swap format
|
||||
##include "cas.isa"
|
||||
|
||||
//Include the trap format
|
||||
##include "trap.isa"
|
||||
|
||||
|
|
|
@ -32,100 +32,6 @@
|
|||
// Mem instructions
|
||||
//
|
||||
|
||||
output header {{
|
||||
/**
|
||||
* Base class for memory operations.
|
||||
*/
|
||||
class Mem : public SparcStaticInst
|
||||
{
|
||||
protected:
|
||||
|
||||
// Constructor
|
||||
Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
|
||||
SparcStaticInst(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for memory operations which use an immediate offset.
|
||||
*/
|
||||
class MemImm : public Mem
|
||||
{
|
||||
protected:
|
||||
|
||||
// Constructor
|
||||
MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
|
||||
Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
|
||||
const int32_t imm;
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
std::string Mem::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
bool load = flags[IsLoad];
|
||||
bool save = flags[IsStore];
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
if(save)
|
||||
{
|
||||
printReg(response, _srcRegIdx[0]);
|
||||
ccprintf(response, ", ");
|
||||
}
|
||||
ccprintf(response, "[ ");
|
||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
||||
ccprintf(response, " + ");
|
||||
printReg(response, _srcRegIdx[!save ? 1 : 2]);
|
||||
ccprintf(response, " ]");
|
||||
if(load)
|
||||
{
|
||||
ccprintf(response, ", ");
|
||||
printReg(response, _destRegIdx[0]);
|
||||
}
|
||||
|
||||
return response.str();
|
||||
}
|
||||
|
||||
std::string MemImm::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
bool load = flags[IsLoad];
|
||||
bool save = flags[IsStore];
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
if(save)
|
||||
{
|
||||
printReg(response, _srcRegIdx[0]);
|
||||
ccprintf(response, ", ");
|
||||
}
|
||||
ccprintf(response, "[ ");
|
||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
||||
if(imm >= 0)
|
||||
ccprintf(response, " + 0x%x ]", imm);
|
||||
else
|
||||
ccprintf(response, " + -0x%x ]", -imm);
|
||||
if(load)
|
||||
{
|
||||
ccprintf(response, ", ");
|
||||
printReg(response, _destRegIdx[0]);
|
||||
}
|
||||
|
||||
return response.str();
|
||||
}
|
||||
}};
|
||||
|
||||
def template MemDeclare {{
|
||||
/**
|
||||
* Static instruction class for "%(mnemonic)s".
|
||||
|
@ -156,7 +62,7 @@ let {{
|
|||
header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
|
||||
decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
|
||||
decode_block = ROrImmDecode.subst(iop)
|
||||
exec_output = doSplitExecute(code, addrCalcReg, addrCalcImm, execute,
|
||||
exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, execute,
|
||||
faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags)
|
||||
return (header_output, decoder_output, exec_output, decode_block)
|
||||
}};
|
||||
|
|
|
@ -56,14 +56,14 @@ output header {{
|
|||
{}
|
||||
};
|
||||
|
||||
class BlockMemMicro : public SparcDelayedMicroInst
|
||||
class BlockMemMicro : public SparcMicroInst
|
||||
{
|
||||
protected:
|
||||
|
||||
// Constructor
|
||||
BlockMemMicro(const char *mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, int8_t _offset) :
|
||||
SparcDelayedMicroInst(mnem, _machInst, __opClass),
|
||||
SparcMicroInst(mnem, _machInst, __opClass),
|
||||
offset(_offset)
|
||||
{}
|
||||
|
||||
|
@ -290,6 +290,8 @@ let {{
|
|||
flag_code = ''
|
||||
if (microPc == 7):
|
||||
flag_code = "flags[IsLastMicroOp] = true;"
|
||||
else:
|
||||
flag_code = "flags[IsDelayedCommit] = true;"
|
||||
pcedCode = matcher.sub("Frd_%d" % microPc, code)
|
||||
iop = InstObjParams(name, Name, 'BlockMem', pcedCode,
|
||||
opt_flags, {"ea_code": addrCalcReg,
|
||||
|
@ -301,7 +303,7 @@ let {{
|
|||
"set_flags": flag_code})
|
||||
decoder_output += BlockMemMicroConstructor.subst(iop)
|
||||
decoder_output += BlockMemMicroConstructor.subst(iop_imm)
|
||||
exec_output += doSplitExecute(
|
||||
exec_output += doDualSplitExecute(
|
||||
pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
|
||||
makeMicroName(name, microPc),
|
||||
makeMicroName(name + "Imm", microPc),
|
||||
|
|
|
@ -41,5 +41,5 @@
|
|||
//Include the block memory format
|
||||
##include "blockmem.isa"
|
||||
|
||||
//Include the load/store memory format
|
||||
//Include the load/store and cas memory format
|
||||
##include "loadstore.isa"
|
||||
|
|
|
@ -33,6 +33,100 @@
|
|||
// Mem utility templates and functions
|
||||
//
|
||||
|
||||
output header {{
|
||||
/**
|
||||
* Base class for memory operations.
|
||||
*/
|
||||
class Mem : public SparcStaticInst
|
||||
{
|
||||
protected:
|
||||
|
||||
// Constructor
|
||||
Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
|
||||
SparcStaticInst(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for memory operations which use an immediate offset.
|
||||
*/
|
||||
class MemImm : public Mem
|
||||
{
|
||||
protected:
|
||||
|
||||
// Constructor
|
||||
MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
|
||||
Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
|
||||
{}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
|
||||
const int32_t imm;
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
std::string Mem::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
bool load = flags[IsLoad];
|
||||
bool save = flags[IsStore];
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
if(save)
|
||||
{
|
||||
printReg(response, _srcRegIdx[0]);
|
||||
ccprintf(response, ", ");
|
||||
}
|
||||
ccprintf(response, "[ ");
|
||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
||||
ccprintf(response, " + ");
|
||||
printReg(response, _srcRegIdx[!save ? 1 : 2]);
|
||||
ccprintf(response, " ]");
|
||||
if(load)
|
||||
{
|
||||
ccprintf(response, ", ");
|
||||
printReg(response, _destRegIdx[0]);
|
||||
}
|
||||
|
||||
return response.str();
|
||||
}
|
||||
|
||||
std::string MemImm::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream response;
|
||||
bool load = flags[IsLoad];
|
||||
bool save = flags[IsStore];
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
if(save)
|
||||
{
|
||||
printReg(response, _srcRegIdx[0]);
|
||||
ccprintf(response, ", ");
|
||||
}
|
||||
ccprintf(response, "[ ");
|
||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
||||
if(imm >= 0)
|
||||
ccprintf(response, " + 0x%x ]", imm);
|
||||
else
|
||||
ccprintf(response, " + -0x%x ]", -imm);
|
||||
if(load)
|
||||
{
|
||||
ccprintf(response, ", ");
|
||||
printReg(response, _destRegIdx[0]);
|
||||
}
|
||||
|
||||
return response.str();
|
||||
}
|
||||
}};
|
||||
|
||||
//This template provides the execute functions for a load
|
||||
def template LoadExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||
|
@ -102,6 +196,9 @@ def template StoreExecute {{
|
|||
{
|
||||
Fault fault = NoFault;
|
||||
uint64_t write_result = 0;
|
||||
//This is to support the conditional store in cas instructions.
|
||||
//It should be optomized out in all the others
|
||||
bool storeCond = true;
|
||||
Addr EA;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
|
@ -112,7 +209,7 @@ def template StoreExecute {{
|
|||
{
|
||||
%(code)s;
|
||||
}
|
||||
if(fault == NoFault)
|
||||
if(storeCond && fault == NoFault)
|
||||
{
|
||||
fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
|
||||
}
|
||||
|
@ -130,6 +227,7 @@ def template StoreExecute {{
|
|||
{
|
||||
Fault fault = NoFault;
|
||||
uint64_t write_result = 0;
|
||||
bool storeCond = true;
|
||||
Addr EA;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
|
@ -140,7 +238,7 @@ def template StoreExecute {{
|
|||
{
|
||||
%(code)s;
|
||||
}
|
||||
if(fault == NoFault)
|
||||
if(storeCond && fault == NoFault)
|
||||
{
|
||||
fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
|
||||
}
|
||||
|
@ -204,23 +302,29 @@ let {{
|
|||
//and in the other they're distributed across two. Also note that for
|
||||
//execute functions, the name of the base class doesn't matter.
|
||||
let {{
|
||||
def doSplitExecute(code, eaRegCode, eaImmCode, execute,
|
||||
def doSplitExecute(code, eaCode, execute,
|
||||
faultCode, name, Name, opt_flags):
|
||||
codeIop = InstObjParams(name, Name, '', code, opt_flags)
|
||||
eaIop = InstObjParams(name, Name, '', eaCode,
|
||||
opt_flags, {"fault_check": faultCode})
|
||||
iop = InstObjParams(name, Name, '', code, opt_flags,
|
||||
{"fault_check": faultCode, "ea_code" : eaCode})
|
||||
(iop.ea_decl,
|
||||
iop.ea_rd,
|
||||
iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)
|
||||
(iop.code_decl,
|
||||
iop.code_rd,
|
||||
iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb)
|
||||
return execute.subst(iop)
|
||||
|
||||
|
||||
def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
|
||||
faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags):
|
||||
codeIop = InstObjParams(nameReg, NameReg, '', code, opt_flags)
|
||||
executeCode = ''
|
||||
for (eaCode, name, Name) in (
|
||||
(eaRegCode, nameReg, NameReg),
|
||||
(eaImmCode, nameImm, NameImm)):
|
||||
eaIop = InstObjParams(name, Name, '', eaCode,
|
||||
opt_flags, {"fault_check": faultCode})
|
||||
iop = InstObjParams(name, Name, '', code, opt_flags,
|
||||
{"fault_check": faultCode, "ea_code" : eaCode})
|
||||
(iop.ea_decl,
|
||||
iop.ea_rd,
|
||||
iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)
|
||||
(iop.code_decl,
|
||||
iop.code_rd,
|
||||
iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb)
|
||||
executeCode += execute.subst(iop)
|
||||
executeCode += doSplitExecute(code, eaCode,
|
||||
execute, faultCode, name, Name, opt_flags)
|
||||
return executeCode
|
||||
}};
|
||||
|
|
|
@ -121,15 +121,14 @@ let {{
|
|||
|
||||
// Primary format for integer operate instructions:
|
||||
def format Priv(code, *opt_flags) {{
|
||||
checkCode = '''((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>) ||
|
||||
((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)'''
|
||||
checkCode = "!(Pstate<2:2> || Hpstate<2:2>)"
|
||||
(header_output, decoder_output,
|
||||
exec_output, decode_block) = doPrivFormat(code,
|
||||
checkCode, name, Name, opt_flags + ('IprAccessOp',))
|
||||
}};
|
||||
|
||||
def format HPriv(code, *opt_flags) {{
|
||||
checkCode = "((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)"
|
||||
checkCode = "!Hpstate<2:2>"
|
||||
(header_output, decoder_output,
|
||||
exec_output, decode_block) = doPrivFormat(code,
|
||||
checkCode, name, Name, opt_flags + ('IprAccessOp',))
|
||||
|
|
|
@ -61,6 +61,7 @@ def operands {{
|
|||
'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
|
||||
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
|
||||
'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5),
|
||||
'uReg0': ('IntReg', 'udw', 'NumRegularIntRegs+0', 'IsInteger', 6),
|
||||
'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10),
|
||||
'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
|
||||
# Each Frd_N refers to the Nth double precision register from Frd.
|
||||
|
@ -95,18 +96,19 @@ def operands {{
|
|||
'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44),
|
||||
'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45),
|
||||
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46),
|
||||
'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 47),
|
||||
'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 47),
|
||||
'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 48),
|
||||
|
||||
'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 48),
|
||||
'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 49),
|
||||
'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 50),
|
||||
'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 51),
|
||||
'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 52),
|
||||
'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 53),
|
||||
'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 54),
|
||||
'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 49),
|
||||
'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 50),
|
||||
'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 51),
|
||||
'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 52),
|
||||
'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 53),
|
||||
'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 54),
|
||||
'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 55),
|
||||
|
||||
'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 55),
|
||||
'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56),
|
||||
'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 56),
|
||||
'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 57),
|
||||
# Mem gets a large number so it's always last
|
||||
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
|
||||
|
||||
|
|
|
@ -57,14 +57,17 @@ namespace SparcISA
|
|||
//This makes sure the big endian versions of certain functions are used.
|
||||
using namespace BigEndianGuest;
|
||||
|
||||
// Alpha Does NOT have a delay slot
|
||||
// SPARC has a delay slot
|
||||
#define ISA_HAS_DELAY_SLOT 1
|
||||
|
||||
//TODO this needs to be a SPARC Noop
|
||||
// Alpha UNOP (ldq_u r31,0(r0))
|
||||
const MachInst NoopMachInst = 0x2ffe0000;
|
||||
// SPARC NOP (sethi %(hi(0), g0)
|
||||
const MachInst NoopMachInst = 0x01000000;
|
||||
|
||||
const int NumIntRegs = 32;
|
||||
const int NumRegularIntRegs = 32;
|
||||
const int NumMicroIntRegs = 1;
|
||||
const int NumIntRegs =
|
||||
NumRegularIntRegs +
|
||||
NumMicroIntRegs;
|
||||
const int NumFloatRegs = 64;
|
||||
const int NumMiscRegs = 40;
|
||||
|
||||
|
@ -87,7 +90,7 @@ namespace SparcISA
|
|||
const int MaxPGL = 2;
|
||||
|
||||
// NWINDOWS - number of register windows, can be 3 to 32
|
||||
const int NWindows = 32;
|
||||
const int NWindows = 8;
|
||||
|
||||
// semantically meaningful register indices
|
||||
const int ZeroReg = 0; // architecturally meaningful
|
||||
|
|
|
@ -202,282 +202,164 @@ MiscReg MiscRegFile::readReg(int miscReg)
|
|||
}
|
||||
}
|
||||
|
||||
MiscReg MiscRegFile::readRegWithEffect(int miscReg,
|
||||
Fault &fault, ThreadContext * tc)
|
||||
MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
|
||||
{
|
||||
fault = NoFault;
|
||||
switch (miscReg) {
|
||||
case MISCREG_Y:
|
||||
case MISCREG_CCR:
|
||||
case MISCREG_ASI:
|
||||
return readReg(miscReg);
|
||||
|
||||
case MISCREG_TICK:
|
||||
case MISCREG_PRIVTICK:
|
||||
// Check for reading privilege
|
||||
if (tickFields.npt && !isNonPriv()) {
|
||||
fault = new PrivilegedAction;
|
||||
return 0;
|
||||
}
|
||||
return tc->getCpuPtr()->curCycle() - tickFields.counter |
|
||||
tickFields.npt << 63;
|
||||
case MISCREG_PC:
|
||||
return tc->readPC();
|
||||
case MISCREG_FPRS:
|
||||
fault = new UnimpFault("FPU not implemented\n");
|
||||
return 0;
|
||||
panic("FPU not implemented\n");
|
||||
case MISCREG_PCR:
|
||||
fault = new UnimpFault("Performance Instrumentation not impl\n");
|
||||
return 0;
|
||||
case MISCREG_PIC:
|
||||
fault = new UnimpFault("Performance Instrumentation not impl\n");
|
||||
return 0;
|
||||
case MISCREG_GSR:
|
||||
return readReg(miscReg);
|
||||
|
||||
/** Privilged Registers */
|
||||
case MISCREG_TPC:
|
||||
case MISCREG_TNPC:
|
||||
case MISCREG_TSTATE:
|
||||
case MISCREG_TT:
|
||||
if (tl == 0) {
|
||||
fault = new IllegalInstruction;
|
||||
return 0;
|
||||
} // NOTE THE FALL THROUGH!
|
||||
case MISCREG_PSTATE:
|
||||
case MISCREG_TL:
|
||||
return readReg(miscReg);
|
||||
|
||||
case MISCREG_TBA:
|
||||
return readReg(miscReg) & ULL(~0x7FFF);
|
||||
|
||||
case MISCREG_PIL:
|
||||
|
||||
case MISCREG_CWP:
|
||||
case MISCREG_CANSAVE:
|
||||
case MISCREG_CANRESTORE:
|
||||
case MISCREG_CLEANWIN:
|
||||
case MISCREG_OTHERWIN:
|
||||
case MISCREG_WSTATE:
|
||||
case MISCREG_GL:
|
||||
return readReg(miscReg);
|
||||
panic("Performance Instrumentation not impl\n");
|
||||
|
||||
/** Floating Point Status Register */
|
||||
case MISCREG_FSR:
|
||||
panic("Floating Point not implemented\n");
|
||||
default:
|
||||
#if FULL_SYSTEM
|
||||
return readFSRegWithEffect(miscReg, fault, tc);
|
||||
#else
|
||||
fault = new IllegalInstruction;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
return readReg(miscReg);
|
||||
}
|
||||
|
||||
Fault MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
||||
void MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
||||
{
|
||||
switch (miscReg) {
|
||||
case MISCREG_Y:
|
||||
y = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_CCR:
|
||||
ccr = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_ASI:
|
||||
asi = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_FPRS:
|
||||
fprs = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_TICK:
|
||||
tick = val;
|
||||
return NoFault;
|
||||
tick = val;
|
||||
break;
|
||||
case MISCREG_PCR:
|
||||
case MISCREG_PIC:
|
||||
panic("ASR number %d not implemented\n", miscReg - AsrStart);
|
||||
case MISCREG_GSR:
|
||||
gsr = val;
|
||||
break;
|
||||
case MISCREG_SOFTINT:
|
||||
softint = val;
|
||||
return NoFault;
|
||||
softint = val;
|
||||
break;
|
||||
case MISCREG_TICK_CMPR:
|
||||
tick_cmpr = val;
|
||||
return NoFault;
|
||||
tick_cmpr = val;
|
||||
break;
|
||||
case MISCREG_STICK:
|
||||
stick = val;
|
||||
return NoFault;
|
||||
stick = val;
|
||||
break;
|
||||
case MISCREG_STICK_CMPR:
|
||||
stick_cmpr = val;
|
||||
return NoFault;
|
||||
stick_cmpr = val;
|
||||
break;
|
||||
|
||||
/** Privilged Registers */
|
||||
case MISCREG_TPC:
|
||||
tpc[tl-1] = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_TNPC:
|
||||
tnpc[tl-1] = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_TSTATE:
|
||||
tstate[tl-1] = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_TT:
|
||||
tt[tl-1] = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_PRIVTICK:
|
||||
panic("Priviliged access to tick regesiters not implemented\n");
|
||||
case MISCREG_TBA:
|
||||
tba = val;
|
||||
return NoFault;
|
||||
// clear lower 7 bits on writes.
|
||||
tba = val & ULL(~0x7FFF);
|
||||
break;
|
||||
case MISCREG_PSTATE:
|
||||
pstate = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_TL:
|
||||
tl = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_PIL:
|
||||
pil = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_CWP:
|
||||
cwp = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_CANSAVE:
|
||||
cansave = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_CANRESTORE:
|
||||
canrestore = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_CLEANWIN:
|
||||
cleanwin = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_OTHERWIN:
|
||||
otherwin = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_WSTATE:
|
||||
wstate = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_GL:
|
||||
gl = val;
|
||||
return NoFault;
|
||||
break;
|
||||
|
||||
/** Hyper privileged registers */
|
||||
case MISCREG_HPSTATE:
|
||||
hpstate = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_HTSTATE:
|
||||
htstate[tl-1] = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_HINTP:
|
||||
panic("HINTP not implemented\n");
|
||||
case MISCREG_HTBA:
|
||||
htba = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_STRAND_STS_REG:
|
||||
strandStatusReg = val;
|
||||
return NoFault;
|
||||
break;
|
||||
case MISCREG_HSTICK_CMPR:
|
||||
hstick_cmpr = val;
|
||||
return NoFault;
|
||||
break;
|
||||
|
||||
/** Floating Point Status Register */
|
||||
case MISCREG_FSR:
|
||||
fsr = val;
|
||||
return NoFault;
|
||||
break;
|
||||
default:
|
||||
panic("Miscellaneous register %d not implemented\n", miscReg);
|
||||
}
|
||||
}
|
||||
|
||||
Fault MiscRegFile::setRegWithEffect(int miscReg,
|
||||
void MiscRegFile::setRegWithEffect(int miscReg,
|
||||
const MiscReg &val, ThreadContext * tc)
|
||||
{
|
||||
const uint64_t Bit64 = (1ULL << 63);
|
||||
switch (miscReg) {
|
||||
case MISCREG_Y:
|
||||
case MISCREG_CCR:
|
||||
case MISCREG_ASI:
|
||||
setReg(miscReg, val);
|
||||
return NoFault;
|
||||
case MISCREG_PRIVTICK:
|
||||
case MISCREG_TICK:
|
||||
if (isNonPriv())
|
||||
return new PrivilegedOpcode;
|
||||
if (isPriv())
|
||||
return new PrivilegedAction;
|
||||
tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64;
|
||||
tickFields.npt = val & Bit64 ? 1 : 0;
|
||||
return NoFault;
|
||||
case MISCREG_PC:
|
||||
return new IllegalInstruction;
|
||||
break;
|
||||
case MISCREG_FPRS:
|
||||
return new UnimpFault("FPU not implemented\n");
|
||||
//Configure the fpu based on the fprs
|
||||
break;
|
||||
case MISCREG_PCR:
|
||||
return new UnimpFault("Performance Instrumentation not impl\n");
|
||||
case MISCREG_PIC:
|
||||
return new UnimpFault("Performance Instrumentation not impl\n");
|
||||
case MISCREG_GSR:
|
||||
return setReg(miscReg, val);
|
||||
|
||||
/** Privilged Registers */
|
||||
case MISCREG_TPC:
|
||||
case MISCREG_TNPC:
|
||||
case MISCREG_TSTATE:
|
||||
case MISCREG_TT:
|
||||
if (tl == 0)
|
||||
return new IllegalInstruction;
|
||||
setReg(miscReg, val);
|
||||
return NoFault;
|
||||
|
||||
case MISCREG_TBA:
|
||||
// clear lower 7 bits on writes.
|
||||
setReg(miscReg, val & ULL(~0x7FFF));
|
||||
return NoFault;
|
||||
|
||||
case MISCREG_PSTATE:
|
||||
setReg(miscReg, val);
|
||||
return NoFault;
|
||||
|
||||
case MISCREG_TL:
|
||||
if (isHyperPriv() && val > MaxTL)
|
||||
setReg(miscReg, MaxTL);
|
||||
else if (isPriv() && !isHyperPriv() && val > MaxPTL)
|
||||
setReg(miscReg, MaxPTL);
|
||||
else
|
||||
setReg(miscReg, val);
|
||||
return NoFault;
|
||||
|
||||
//Set up performance counting based on pcr value
|
||||
break;
|
||||
case MISCREG_CWP:
|
||||
tc->changeRegFileContext(CONTEXT_CWP, val);
|
||||
case MISCREG_CANSAVE:
|
||||
case MISCREG_CANRESTORE:
|
||||
case MISCREG_CLEANWIN:
|
||||
case MISCREG_OTHERWIN:
|
||||
case MISCREG_WSTATE:
|
||||
setReg(miscReg, val);
|
||||
return NoFault;
|
||||
|
||||
break;
|
||||
case MISCREG_GL:
|
||||
int newval;
|
||||
if (isHyperPriv() && val > MaxGL)
|
||||
newval = MaxGL;
|
||||
else if (isPriv() && !isHyperPriv() && val > MaxPGL)
|
||||
newval = MaxPGL;
|
||||
else
|
||||
newval = val;
|
||||
tc->changeRegFileContext(CONTEXT_GLOBALS, newval);
|
||||
setReg(miscReg, newval);
|
||||
return NoFault;
|
||||
|
||||
/** Floating Point Status Register */
|
||||
case MISCREG_FSR:
|
||||
panic("Floating Point not implemented\n");
|
||||
default:
|
||||
#if FULL_SYSTEM
|
||||
setFSRegWithEffect(miscReg, val, tc);
|
||||
#else
|
||||
return new IllegalInstruction;
|
||||
#endif
|
||||
tc->changeRegFileContext(CONTEXT_GLOBALS, val);
|
||||
break;
|
||||
}
|
||||
setReg(miscReg, val);
|
||||
}
|
||||
|
||||
void MiscRegFile::serialize(std::ostream & os)
|
||||
|
|
|
@ -56,7 +56,6 @@ namespace SparcISA
|
|||
MISCREG_CCR = AsrStart + 2,
|
||||
MISCREG_ASI = AsrStart + 3,
|
||||
MISCREG_TICK = AsrStart + 4,
|
||||
MISCREG_PC = AsrStart + 5,
|
||||
MISCREG_FPRS = AsrStart + 6,
|
||||
MISCREG_PCR = AsrStart + 16,
|
||||
MISCREG_PIC = AsrStart + 17,
|
||||
|
@ -366,31 +365,13 @@ namespace SparcISA
|
|||
reset();
|
||||
}
|
||||
|
||||
/** read a value out of an either an SE or FS IPR. No checking is done
|
||||
* about SE vs. FS as this is mostly used to copy the regfile. Thus more
|
||||
* register are copied that are necessary for FS. However this prevents
|
||||
* a bunch of ifdefs and is rarely called so is not performance
|
||||
* criticial. */
|
||||
MiscReg readReg(int miscReg);
|
||||
|
||||
/** Read a value from an IPR. Only the SE iprs are here and the rest
|
||||
* are are readFSRegWithEffect (which is called by readRegWithEffect()).
|
||||
* Checking is done for permission based on state bits in the miscreg
|
||||
* file. */
|
||||
MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
|
||||
MiscReg readRegWithEffect(int miscReg, ThreadContext *tc);
|
||||
|
||||
/** write a value into an either an SE or FS IPR. No checking is done
|
||||
* about SE vs. FS as this is mostly used to copy the regfile. Thus more
|
||||
* register are copied that are necessary for FS. However this prevents
|
||||
* a bunch of ifdefs and is rarely called so is not performance
|
||||
* criticial.*/
|
||||
Fault setReg(int miscReg, const MiscReg &val);
|
||||
void setReg(int miscReg, const MiscReg &val);
|
||||
|
||||
/** Write a value into an IPR. Only the SE iprs are here and the rest
|
||||
* are are setFSRegWithEffect (which is called by setRegWithEffect()).
|
||||
* Checking is done for permission based on state bits in the miscreg
|
||||
* file. */
|
||||
Fault setRegWithEffect(int miscReg,
|
||||
void setRegWithEffect(int miscReg,
|
||||
const MiscReg &val, ThreadContext * tc);
|
||||
|
||||
void serialize(std::ostream & os);
|
||||
|
|
|
@ -66,6 +66,10 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
|
|||
|
||||
// Set pointer for next thread stack. Reserve 8M for main stack.
|
||||
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
|
||||
|
||||
//Initialize these to 0s
|
||||
fillStart = 0;
|
||||
spillStart = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -88,15 +92,19 @@ SparcLiveProcess::startup()
|
|||
*/
|
||||
|
||||
//No windows contain info from other programs
|
||||
threadContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0);
|
||||
threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0);
|
||||
//There are no windows to pop
|
||||
threadContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0);
|
||||
threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0);
|
||||
//All windows are available to save into
|
||||
threadContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2);
|
||||
threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2);
|
||||
//All windows are "clean"
|
||||
threadContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows);
|
||||
threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows);
|
||||
//Start with register window 0
|
||||
threadContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
|
||||
threadContexts[0]->setMiscReg(MISCREG_CWP, 0);
|
||||
//Always use spill and fill traps 0
|
||||
threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0);
|
||||
//Set the trap level to 0
|
||||
threadContexts[0]->setMiscReg(MISCREG_TL, 0);
|
||||
}
|
||||
|
||||
m5_auxv_t buildAuxVect(int64_t type, int64_t val)
|
||||
|
@ -107,6 +115,83 @@ m5_auxv_t buildAuxVect(int64_t type, int64_t val)
|
|||
return result;
|
||||
}
|
||||
|
||||
//We only use 19 instructions for the trap handlers, but there would be
|
||||
//space for 32 in a real SPARC trap table.
|
||||
const int numFillInsts = 32;
|
||||
const int numSpillInsts = 32;
|
||||
|
||||
MachInst fillHandler[numFillInsts] =
|
||||
{
|
||||
htog(0x87802018), //wr %g0, ASI_AIUP, %asi
|
||||
htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0
|
||||
htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1
|
||||
htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2
|
||||
htog(0xe6dba817), //ldxa [%sp + BIAS + (3*8)] %asi, %l3
|
||||
htog(0xe8dba81f), //ldxa [%sp + BIAS + (4*8)] %asi, %l4
|
||||
htog(0xeadba827), //ldxa [%sp + BIAS + (5*8)] %asi, %l5
|
||||
htog(0xecdba82f), //ldxa [%sp + BIAS + (6*8)] %asi, %l6
|
||||
htog(0xeedba837), //ldxa [%sp + BIAS + (7*8)] %asi, %l7
|
||||
htog(0xf0dba83f), //ldxa [%sp + BIAS + (8*8)] %asi, %i0
|
||||
htog(0xf2dba847), //ldxa [%sp + BIAS + (9*8)] %asi, %i1
|
||||
htog(0xf4dba84f), //ldxa [%sp + BIAS + (10*8)] %asi, %i2
|
||||
htog(0xf6dba857), //ldxa [%sp + BIAS + (11*8)] %asi, %i3
|
||||
htog(0xf8dba85f), //ldxa [%sp + BIAS + (12*8)] %asi, %i4
|
||||
htog(0xfadba867), //ldxa [%sp + BIAS + (13*8)] %asi, %i5
|
||||
htog(0xfcdba86f), //ldxa [%sp + BIAS + (14*8)] %asi, %i6
|
||||
htog(0xfedba877), //ldxa [%sp + BIAS + (15*8)] %asi, %i7
|
||||
htog(0x83880000), //restored
|
||||
htog(0x83F00000), //retry
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000) //illtrap
|
||||
};
|
||||
|
||||
MachInst spillHandler[numSpillInsts] =
|
||||
{
|
||||
htog(0x87802018), //wr %g0, ASI_AIUP, %asi
|
||||
htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi
|
||||
htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi
|
||||
htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi
|
||||
htog(0xe6f3a817), //stxa %l3, [%sp + BIAS + (3*8)] %asi
|
||||
htog(0xe8f3a81f), //stxa %l4, [%sp + BIAS + (4*8)] %asi
|
||||
htog(0xeaf3a827), //stxa %l5, [%sp + BIAS + (5*8)] %asi
|
||||
htog(0xecf3a82f), //stxa %l6, [%sp + BIAS + (6*8)] %asi
|
||||
htog(0xeef3a837), //stxa %l7, [%sp + BIAS + (7*8)] %asi
|
||||
htog(0xf0f3a83f), //stxa %i0, [%sp + BIAS + (8*8)] %asi
|
||||
htog(0xf2f3a847), //stxa %i1, [%sp + BIAS + (9*8)] %asi
|
||||
htog(0xf4f3a84f), //stxa %i2, [%sp + BIAS + (10*8)] %asi
|
||||
htog(0xf6f3a857), //stxa %i3, [%sp + BIAS + (11*8)] %asi
|
||||
htog(0xf8f3a85f), //stxa %i4, [%sp + BIAS + (12*8)] %asi
|
||||
htog(0xfaf3a867), //stxa %i5, [%sp + BIAS + (13*8)] %asi
|
||||
htog(0xfcf3a86f), //stxa %i6, [%sp + BIAS + (14*8)] %asi
|
||||
htog(0xfef3a877), //stxa %i7, [%sp + BIAS + (15*8)] %asi
|
||||
htog(0x81880000), //saved
|
||||
htog(0x83F00000), //retry
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000), //illtrap
|
||||
htog(0x00000000) //illtrap
|
||||
};
|
||||
|
||||
void
|
||||
SparcLiveProcess::argsInit(int intSize, int pageSize)
|
||||
{
|
||||
|
@ -317,6 +402,17 @@ SparcLiveProcess::argsInit(int intSize, int pageSize)
|
|||
|
||||
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
|
||||
|
||||
//Stuff the trap handlers into the processes address space.
|
||||
//Since the stack grows down and is the highest area in the processes
|
||||
//address space, we can put stuff above it and stay out of the way.
|
||||
int fillSize = sizeof(MachInst) * numFillInsts;
|
||||
int spillSize = sizeof(MachInst) * numSpillInsts;
|
||||
fillStart = stack_base;
|
||||
spillStart = fillStart + fillSize;
|
||||
initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler, fillSize);
|
||||
initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler, spillSize);
|
||||
|
||||
//Set up the thread context to start running the process
|
||||
threadContexts[0]->setIntReg(ArgumentReg0, argc);
|
||||
threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
|
||||
threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
|
||||
|
|
|
@ -55,6 +55,9 @@ class SparcLiveProcess : public LiveProcess
|
|||
|
||||
static const Addr StackBias = 2047;
|
||||
|
||||
//The locations of the fill and spill handlers
|
||||
Addr fillStart, spillStart;
|
||||
|
||||
std::vector<m5_auxv_t> auxv;
|
||||
|
||||
SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
|
||||
|
@ -71,6 +74,12 @@ class SparcLiveProcess : public LiveProcess
|
|||
|
||||
void argsInit(int intSize, int pageSize);
|
||||
|
||||
Addr readFillStart()
|
||||
{ return fillStart; }
|
||||
|
||||
Addr readSpillStart()
|
||||
{ return spillStart; }
|
||||
|
||||
};
|
||||
|
||||
#endif // __SPARC_PROCESS_HH__
|
||||
|
|
|
@ -82,18 +82,21 @@ MiscReg RegFile::readMiscReg(int miscReg)
|
|||
MiscReg RegFile::readMiscRegWithEffect(int miscReg,
|
||||
Fault &fault, ThreadContext *tc)
|
||||
{
|
||||
return miscRegFile.readRegWithEffect(miscReg, fault, tc);
|
||||
fault = NoFault;
|
||||
return miscRegFile.readRegWithEffect(miscReg, tc);
|
||||
}
|
||||
|
||||
Fault RegFile::setMiscReg(int miscReg, const MiscReg &val)
|
||||
{
|
||||
return miscRegFile.setReg(miscReg, val);
|
||||
miscRegFile.setReg(miscReg, val);
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val,
|
||||
ThreadContext * tc)
|
||||
{
|
||||
return miscRegFile.setRegWithEffect(miscReg, val, tc);
|
||||
miscRegFile.setRegWithEffect(miscReg, val, tc);
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
FloatReg RegFile::readFloatReg(int floatReg, int width)
|
||||
|
|
|
@ -69,4 +69,28 @@ sext(uint64_t val)
|
|||
return sign_bit ? (val | ~mask(N)) : val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return val with bits first to last set to bit_val
|
||||
*/
|
||||
template <class T, class B>
|
||||
inline
|
||||
T
|
||||
insertBits(T val, int first, int last, B bit_val)
|
||||
{
|
||||
T bmask = mask(first - last + 1) << last;
|
||||
return ((bit_val << last) & bmask) | (val & ~bmask);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function to replace bits first to last of val with bit_val
|
||||
* in place.
|
||||
*/
|
||||
template <class T, class B>
|
||||
inline
|
||||
void
|
||||
replaceBits(T& val, int first, int last, B bit_val)
|
||||
{
|
||||
val = insertBits(val, first, last, bit_val);
|
||||
}
|
||||
|
||||
#endif // __BASE_BITFIELD_HH__
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
#include "arch/faults.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "base/timebuf.hh"
|
||||
#include "cpu/inst_seq.hh"
|
||||
#include "cpu/ozone/rename_table.hh"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Authors: Kevin Lim
|
||||
*/
|
||||
|
||||
#include "arch/faults.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "cpu/ozone/dyn_inst.hh"
|
||||
#include "kern/kernel_stats.hh"
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "config/use_checker.hh"
|
||||
|
||||
#include "arch/faults.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "arch/utility.hh"
|
||||
#include "base/statistics.hh"
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include <list>
|
||||
|
||||
#include "arch/faults.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "base/timebuf.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "cpu/inst_seq.hh"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Authors: Kevin Lim
|
||||
*/
|
||||
|
||||
#include "arch/faults.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "arch/types.hh"
|
||||
#include "cpu/ozone/inorder_back_end.hh"
|
||||
#include "cpu/ozone/thread_state.hh"
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "arch/faults.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "base/timebuf.hh"
|
||||
#include "cpu/inst_seq.hh"
|
||||
#include "cpu/ozone/rename_table.hh"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#ifndef __CPU_OZONE_THREAD_STATE_HH__
|
||||
#define __CPU_OZONE_THREAD_STATE_HH__
|
||||
|
||||
#include "arch/faults.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "arch/types.hh"
|
||||
#include "arch/regfile.hh"
|
||||
#include "base/callback.hh"
|
||||
|
|
|
@ -188,8 +188,11 @@ AtomicSimpleCPU::resume()
|
|||
|
||||
changeState(SimObject::Running);
|
||||
if (thread->status() == ThreadContext::Active) {
|
||||
if (!tickEvent.scheduled())
|
||||
tickEvent.schedule(curTick);
|
||||
if (!tickEvent.scheduled()) {
|
||||
Tick nextTick = curTick + cycles(1) - 1;
|
||||
nextTick -= (nextTick % (cycles(1)));
|
||||
tickEvent.schedule(nextTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +220,9 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
|
|||
ThreadContext *tc = threadContexts[i];
|
||||
if (tc->status() == ThreadContext::Active && _status != Running) {
|
||||
_status = Running;
|
||||
tickEvent.schedule(curTick);
|
||||
Tick nextTick = curTick + cycles(1) - 1;
|
||||
nextTick -= (nextTick % (cycles(1)));
|
||||
tickEvent.schedule(nextTick);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +239,10 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay)
|
|||
assert(!tickEvent.scheduled());
|
||||
|
||||
notIdleFraction++;
|
||||
tickEvent.schedule(curTick + cycles(delay));
|
||||
//Make sure ticks are still on multiples of cycles
|
||||
Tick nextTick = curTick + cycles(delay + 1) - 1;
|
||||
nextTick -= (nextTick % (cycles(1)));
|
||||
tickEvent.schedule(nextTick);
|
||||
_status = Running;
|
||||
}
|
||||
|
||||
|
|
|
@ -401,13 +401,15 @@ BaseSimpleCPU::preExecute()
|
|||
StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC()));
|
||||
if (instPtr->isMacroOp()) {
|
||||
curMacroStaticInst = instPtr;
|
||||
curStaticInst = curMacroStaticInst->fetchMicroOp(0);
|
||||
curStaticInst = curMacroStaticInst->
|
||||
fetchMicroOp(thread->readMicroPC());
|
||||
} else {
|
||||
curStaticInst = instPtr;
|
||||
}
|
||||
} else {
|
||||
//Read the next micro op from the macro op
|
||||
curStaticInst = curMacroStaticInst->fetchMicroOp(thread->readMicroPC());
|
||||
curStaticInst = curMacroStaticInst->
|
||||
fetchMicroOp(thread->readMicroPC());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ ThreadState::serialize(std::ostream &os)
|
|||
// thread_num and cpu_id are deterministic from the config
|
||||
SERIALIZE_SCALAR(funcExeInst);
|
||||
SERIALIZE_SCALAR(inst);
|
||||
SERIALIZE_SCALAR(microPC);
|
||||
SERIALIZE_SCALAR(nextMicroPC);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
Tick quiesceEndTick = 0;
|
||||
|
@ -81,6 +83,8 @@ ThreadState::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
// thread_num and cpu_id are deterministic from the config
|
||||
UNSERIALIZE_SCALAR(funcExeInst);
|
||||
UNSERIALIZE_SCALAR(inst);
|
||||
UNSERIALIZE_SCALAR(microPC);
|
||||
UNSERIALIZE_SCALAR(nextMicroPC);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
Tick quiesceEndTick;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "base/inet.hh"
|
||||
#include "dev/i8254xGBe.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/stats.hh"
|
||||
#include "sim/system.hh"
|
||||
|
@ -66,12 +67,17 @@ IGbE::IGbE(Params *p)
|
|||
regs.tctl.reg = 0;
|
||||
regs.manc.reg = 0;
|
||||
|
||||
regs.pba.rxa = 0x30;
|
||||
regs.pba.txa = 0x10;
|
||||
|
||||
eeOpBits = 0;
|
||||
eeAddrBits = 0;
|
||||
eeDataBits = 0;
|
||||
eeOpcode = 0;
|
||||
|
||||
memset(&flash, 0, EEPROM_SIZE);
|
||||
// clear all 64 16 bit words of the eeprom
|
||||
memset(&flash, 0, EEPROM_SIZE*2);
|
||||
|
||||
// Magic happy checksum value
|
||||
flash[0] = 0xBABA;
|
||||
}
|
||||
|
@ -108,7 +114,7 @@ IGbE::read(PacketPtr pkt)
|
|||
// Only 32bit accesses allowed
|
||||
assert(pkt->getSize() == 4);
|
||||
|
||||
DPRINTF(Ethernet, "Read device register %#X\n", daddr);
|
||||
//DPRINTF(Ethernet, "Read device register %#X\n", daddr);
|
||||
|
||||
pkt->allocate();
|
||||
|
||||
|
@ -116,6 +122,7 @@ IGbE::read(PacketPtr pkt)
|
|||
/// Handle read of register here
|
||||
///
|
||||
|
||||
|
||||
switch (daddr) {
|
||||
case CTRL:
|
||||
pkt->set<uint32_t>(regs.ctrl.reg);
|
||||
|
@ -141,11 +148,23 @@ IGbE::read(PacketPtr pkt)
|
|||
case TCTL:
|
||||
pkt->set<uint32_t>(regs.tctl.reg);
|
||||
break;
|
||||
case PBA:
|
||||
pkt->set<uint32_t>(regs.pba.reg);
|
||||
break;
|
||||
case WUC:
|
||||
case LEDCTL:
|
||||
pkt->set<uint32_t>(0); // We don't care, so just return 0
|
||||
break;
|
||||
case MANC:
|
||||
pkt->set<uint32_t>(regs.manc.reg);
|
||||
break;
|
||||
default:
|
||||
panic("Read request to unknown register number: %#x\n", daddr);
|
||||
if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) &&
|
||||
!(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) &&
|
||||
!(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4))
|
||||
pkt->set<uint32_t>(0);
|
||||
else
|
||||
panic("Read request to unknown register number: %#x\n", daddr);
|
||||
};
|
||||
|
||||
pkt->result = Packet::Success;
|
||||
|
@ -168,7 +187,7 @@ IGbE::write(PacketPtr pkt)
|
|||
// Only 32bit accesses allowed
|
||||
assert(pkt->getSize() == sizeof(uint32_t));
|
||||
|
||||
DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
|
||||
//DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
|
||||
|
||||
///
|
||||
/// Handle write of register here
|
||||
|
@ -195,10 +214,10 @@ IGbE::write(PacketPtr pkt)
|
|||
eeAddr = eeAddr << 1 | regs.eecd.din;
|
||||
eeAddrBits++;
|
||||
} else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
|
||||
assert(eeAddr < EEPROM_SIZE);
|
||||
DPRINTF(Ethernet, "EEPROM bit read: %d word: %#X\n",
|
||||
flash[eeAddr] >> eeDataBits & 0x1, flash[eeAddr]);
|
||||
regs.eecd.dout = (flash[eeAddr] >> eeDataBits) & 0x1;
|
||||
assert(eeAddr>>1 < EEPROM_SIZE);
|
||||
DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n",
|
||||
flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]);
|
||||
regs.eecd.dout = (flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1;
|
||||
eeDataBits++;
|
||||
} else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) {
|
||||
regs.eecd.dout = 0;
|
||||
|
@ -219,8 +238,9 @@ IGbE::write(PacketPtr pkt)
|
|||
eeAddr = 0;
|
||||
}
|
||||
|
||||
DPRINTF(Ethernet, "EEPROM: opcode: %#X:%d\n",
|
||||
(uint32_t)eeOpcode, (uint32_t) eeOpBits);
|
||||
DPRINTF(EthernetEEPROM, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
|
||||
(uint32_t)eeOpcode, (uint32_t) eeOpBits,
|
||||
(uint32_t)eeAddr>>1, (uint32_t)eeAddrBits);
|
||||
if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI ||
|
||||
eeOpcode == EEPROM_RDSR_OPCODE_SPI ))
|
||||
panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode,
|
||||
|
@ -246,11 +266,22 @@ IGbE::write(PacketPtr pkt)
|
|||
case TCTL:
|
||||
regs.tctl.reg = val;
|
||||
break;
|
||||
case PBA:
|
||||
regs.pba.rxa = val;
|
||||
regs.pba.txa = 64 - regs.pba.rxa;
|
||||
break;
|
||||
case WUC:
|
||||
case LEDCTL:
|
||||
; // We don't care, so don't store anything
|
||||
break;
|
||||
case MANC:
|
||||
regs.manc.reg = val;
|
||||
break;
|
||||
default:
|
||||
panic("Write request to unknown register number: %#x\n", daddr);
|
||||
if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) &&
|
||||
!(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) &&
|
||||
!(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4))
|
||||
panic("Write request to unknown register number: %#x\n", daddr);
|
||||
};
|
||||
|
||||
pkt->result = Packet::Success;
|
||||
|
|
|
@ -33,16 +33,18 @@
|
|||
void
|
||||
SimpleTimingPort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
std::list<PacketPtr>::iterator i = transmitList.begin();
|
||||
std::list<PacketPtr>::iterator end = transmitList.end();
|
||||
std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
|
||||
std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
|
||||
bool done = false;
|
||||
|
||||
while (i != end) {
|
||||
PacketPtr target = *i;
|
||||
while (i != end && !done) {
|
||||
PacketPtr target = i->second;
|
||||
// If the target contains data, and it overlaps the
|
||||
// probed request, need to update data
|
||||
if (target->intersect(pkt))
|
||||
fixPacket(pkt, target);
|
||||
done = fixPacket(pkt, target);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
//Then just do an atomic access and throw away the returned latency
|
||||
|
@ -63,7 +65,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
|
|||
// turn packet around to go back to requester if response expected
|
||||
if (pkt->needsResponse()) {
|
||||
pkt->makeTimingResponse();
|
||||
sendTimingLater(pkt, latency);
|
||||
sendTiming(pkt, latency);
|
||||
}
|
||||
else {
|
||||
if (pkt->cmd != Packet::UpgradeReq)
|
||||
|
@ -78,14 +80,14 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
|
|||
void
|
||||
SimpleTimingPort::recvRetry()
|
||||
{
|
||||
assert(outTiming > 0);
|
||||
assert(!transmitList.empty());
|
||||
if (sendTiming(transmitList.front())) {
|
||||
if (Port::sendTiming(transmitList.front().second)) {
|
||||
transmitList.pop_front();
|
||||
outTiming--;
|
||||
DPRINTF(Bus, "No Longer waiting on retry\n");
|
||||
if (!transmitList.empty())
|
||||
sendTimingLater(transmitList.front(), 1);
|
||||
if (!transmitList.empty()) {
|
||||
Tick time = transmitList.front().first;
|
||||
sendEvent.schedule(time <= curTick ? curTick+1 : time);
|
||||
}
|
||||
}
|
||||
|
||||
if (transmitList.empty() && drainEvent) {
|
||||
|
@ -94,39 +96,62 @@ SimpleTimingPort::recvRetry()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
|
||||
{
|
||||
// Nothing is on the list: add it and schedule an event
|
||||
if (transmitList.empty()) {
|
||||
assert(!sendEvent.scheduled());
|
||||
sendEvent.schedule(curTick+time);
|
||||
transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
|
||||
return;
|
||||
}
|
||||
|
||||
// something is on the list and this belongs at the end
|
||||
if (time+curTick >= transmitList.back().first) {
|
||||
transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
|
||||
return;
|
||||
}
|
||||
// Something is on the list and this belongs somewhere else
|
||||
std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
|
||||
std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
|
||||
bool done = false;
|
||||
|
||||
while (i != end && !done) {
|
||||
if (time+curTick < i->first)
|
||||
transmitList.insert(i,std::pair<Tick,PacketPtr>(time+curTick,pkt));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimpleTimingPort::SendEvent::process()
|
||||
{
|
||||
assert(port->outTiming > 0);
|
||||
if (!port->transmitList.empty() && port->transmitList.front() != packet) {
|
||||
//We are not the head of the list
|
||||
port->transmitList.push_back(packet);
|
||||
} else if (port->sendTiming(packet)) {
|
||||
// send successful
|
||||
if (port->transmitList.size()) {
|
||||
port->transmitList.pop_front();
|
||||
port->outTiming--;
|
||||
if (!port->transmitList.empty())
|
||||
port->sendTimingLater(port->transmitList.front(), 1);
|
||||
assert(port->transmitList.size());
|
||||
assert(port->transmitList.front().first <= curTick);
|
||||
if (port->Port::sendTiming(port->transmitList.front().second)) {
|
||||
//send successful, remove packet
|
||||
port->transmitList.pop_front();
|
||||
if (!port->transmitList.empty()) {
|
||||
Tick time = port->transmitList.front().first;
|
||||
schedule(time <= curTick ? curTick+1 : time);
|
||||
}
|
||||
if (port->transmitList.empty() && port->drainEvent) {
|
||||
port->drainEvent->process();
|
||||
port->drainEvent = NULL;
|
||||
}
|
||||
} else {
|
||||
// send unsuccessful (due to flow control). Will get retry
|
||||
// callback later; save for then if not already
|
||||
DPRINTF(Bus, "Waiting on retry\n");
|
||||
if (!(port->transmitList.front() == packet))
|
||||
port->transmitList.push_back(packet);
|
||||
return;
|
||||
}
|
||||
// send unsuccessful (due to flow control). Will get retry
|
||||
// callback later; save for then if not already
|
||||
DPRINTF(Bus, "Waiting on retry\n");
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
SimpleTimingPort::drain(Event *de)
|
||||
{
|
||||
if (outTiming == 0 && transmitList.size() == 0)
|
||||
if (transmitList.size() == 0)
|
||||
return 0;
|
||||
drainEvent = de;
|
||||
return 1;
|
||||
|
|
|
@ -60,23 +60,22 @@ class SimpleTimingPort : public Port
|
|||
protected:
|
||||
/** A list of outgoing timing response packets that haven't been
|
||||
* serviced yet. */
|
||||
std::list<PacketPtr> transmitList;
|
||||
std::list<std::pair<Tick,PacketPtr> > transmitList;
|
||||
|
||||
/**
|
||||
* This class is used to implemented sendTiming() with a delay. When
|
||||
* a delay is requested a new event is created. When the event time
|
||||
* expires it attempts to send the packet. If it cannot, the packet
|
||||
* is pushed onto the transmit list to be sent when recvRetry() is
|
||||
* called. */
|
||||
* a delay is requested a the event is scheduled if it isn't already.
|
||||
* When the event time expires it attempts to send the packet.
|
||||
* If it cannot, the packet sent when recvRetry() is called.
|
||||
**/
|
||||
class SendEvent : public Event
|
||||
{
|
||||
SimpleTimingPort *port;
|
||||
PacketPtr packet;
|
||||
|
||||
public:
|
||||
SendEvent(SimpleTimingPort *p, PacketPtr pkt, Tick t)
|
||||
: Event(&mainEventQueue), port(p), packet(pkt)
|
||||
{ setFlags(AutoDelete); schedule(curTick + t); }
|
||||
SendEvent(SimpleTimingPort *p)
|
||||
: Event(&mainEventQueue), port(p)
|
||||
{ }
|
||||
|
||||
virtual void process();
|
||||
|
||||
|
@ -84,19 +83,17 @@ class SimpleTimingPort : public Port
|
|||
{ return "Future scheduled sendTiming event"; }
|
||||
};
|
||||
|
||||
|
||||
/** Number of timing requests that are emulating the device timing before
|
||||
* attempting to end up on the bus.
|
||||
*/
|
||||
int outTiming;
|
||||
SendEvent sendEvent;
|
||||
|
||||
/** If we need to drain, keep the drain event around until we're done
|
||||
* here.*/
|
||||
Event *drainEvent;
|
||||
|
||||
/** Schedule a sendTiming() event to be called in the future. */
|
||||
void sendTimingLater(PacketPtr pkt, Tick time)
|
||||
{ outTiming++; new SendEvent(this, pkt, time); }
|
||||
/** Schedule a sendTiming() event to be called in the future.
|
||||
* @param pkt packet to send
|
||||
* @param time increment from now (in ticks) to send packet
|
||||
*/
|
||||
void sendTiming(PacketPtr pkt, Tick time);
|
||||
|
||||
/** This function is notification that the device should attempt to send a
|
||||
* packet again. */
|
||||
|
@ -118,7 +115,7 @@ class SimpleTimingPort : public Port
|
|||
public:
|
||||
|
||||
SimpleTimingPort(std::string pname)
|
||||
: Port(pname), outTiming(0), drainEvent(NULL)
|
||||
: Port(pname), sendEvent(this), drainEvent(NULL)
|
||||
{}
|
||||
|
||||
/** Hook for draining timing accesses from the system. The
|
||||
|
|
|
@ -91,11 +91,6 @@ SimObject::SimObject(const string &_name)
|
|||
state = Running;
|
||||
}
|
||||
|
||||
void
|
||||
SimObject::connect()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SimObject::init()
|
||||
{
|
||||
|
@ -159,21 +154,6 @@ SimObject::regAllStats()
|
|||
Stats::registerResetCallback(&StatResetCB);
|
||||
}
|
||||
|
||||
//
|
||||
// static function: call connect() on all SimObjects.
|
||||
//
|
||||
void
|
||||
SimObject::connectAll()
|
||||
{
|
||||
SimObjectList::iterator i = simObjectList.begin();
|
||||
SimObjectList::iterator end = simObjectList.end();
|
||||
|
||||
for (; i != end; ++i) {
|
||||
SimObject *obj = *i;
|
||||
obj->connect();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// static function: call init() on all SimObjects.
|
||||
//
|
||||
|
|
|
@ -101,9 +101,7 @@ class SimObject : public Serializable, protected StartupCallback
|
|||
// initialization pass of all objects.
|
||||
// Gets invoked after construction, before unserialize.
|
||||
virtual void init();
|
||||
virtual void connect();
|
||||
static void initAll();
|
||||
static void connectAll();
|
||||
|
||||
// register statistics for this object
|
||||
virtual void regStats();
|
||||
|
|
|
@ -91,6 +91,8 @@ uid=100
|
|||
[system.membus]
|
||||
type=Bus
|
||||
bus_id=0
|
||||
clock=1000
|
||||
width=64
|
||||
port=system.physmem.port system.cpu.icache_port system.cpu.dcache_port
|
||||
|
||||
[system.physmem]
|
||||
|
|
|
@ -19,6 +19,8 @@ mem_mode=atomic
|
|||
[system.membus]
|
||||
type=Bus
|
||||
bus_id=0
|
||||
clock=1000
|
||||
width=64
|
||||
|
||||
[system.cpu.workload]
|
||||
type=LiveProcess
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
|
||||
---------- Begin Simulation Statistics ----------
|
||||
host_inst_rate 2175 # Simulator instruction rate (inst/s)
|
||||
host_mem_usage 147292 # Number of bytes of host memory used
|
||||
host_seconds 2.06 # Real time elapsed on the host
|
||||
host_tick_rate 2174 # Simulator tick rate (ticks/s)
|
||||
host_inst_rate 58121 # Simulator instruction rate (inst/s)
|
||||
host_mem_usage 148396 # Number of bytes of host memory used
|
||||
host_seconds 0.08 # Real time elapsed on the host
|
||||
host_tick_rate 57840 # Simulator tick rate (ticks/s)
|
||||
sim_freq 1000000000000 # Frequency of simulated ticks
|
||||
sim_insts 4483 # Number of instructions simulated
|
||||
sim_insts 4863 # Number of instructions simulated
|
||||
sim_seconds 0.000000 # Number of seconds simulated
|
||||
sim_ticks 4482 # Number of ticks simulated
|
||||
sim_ticks 4862 # Number of ticks simulated
|
||||
system.cpu.idle_fraction 0 # Percentage of idle cycles
|
||||
system.cpu.not_idle_fraction 1 # Percentage of non-idle cycles
|
||||
system.cpu.numCycles 4483 # number of cpu cycles simulated
|
||||
system.cpu.num_insts 4483 # Number of instructions executed
|
||||
system.cpu.num_refs 965 # Number of memory references
|
||||
system.cpu.numCycles 4863 # number of cpu cycles simulated
|
||||
system.cpu.num_insts 4863 # Number of instructions executed
|
||||
system.cpu.num_refs 1269 # Number of memory references
|
||||
system.cpu.workload.PROG:num_syscalls 11 # Number of system calls
|
||||
|
||||
---------- End Simulation Statistics ----------
|
||||
|
|
|
@ -5,8 +5,8 @@ The Regents of The University of Michigan
|
|||
All Rights Reserved
|
||||
|
||||
|
||||
M5 compiled Oct 8 2006 14:19:59
|
||||
M5 started Sun Oct 8 14:20:03 2006
|
||||
M5 compiled Oct 27 2006 02:07:29
|
||||
M5 started Fri Oct 27 02:08:08 2006
|
||||
M5 executing on zizzer.eecs.umich.edu
|
||||
command line: build/SPARC_SE/m5.opt -d build/SPARC_SE/tests/opt/quick/00.hello/sparc/linux/simple-atomic tests/run.py quick/00.hello/sparc/linux/simple-atomic
|
||||
Exiting @ tick 4482 because target called exit()
|
||||
command line: build/SPARC_SE/m5.debug -d build/SPARC_SE/tests/debug/quick/00.hello/sparc/linux/simple-atomic tests/run.py quick/00.hello/sparc/linux/simple-atomic
|
||||
Exiting @ tick 4862 because target called exit()
|
||||
|
|
|
@ -20,7 +20,6 @@ print_effaddr=true
|
|||
print_fetchseq=false
|
||||
print_iregs=false
|
||||
print_opclass=true
|
||||
print_reg_delta=false
|
||||
print_thread=true
|
||||
speculative=true
|
||||
trace_system=client
|
||||
|
|
|
@ -1,67 +1,67 @@
|
|||
|
||||
---------- Begin Simulation Statistics ----------
|
||||
host_inst_rate 53689 # Simulator instruction rate (inst/s)
|
||||
host_mem_usage 177104 # Number of bytes of host memory used
|
||||
host_seconds 0.08 # Real time elapsed on the host
|
||||
host_tick_rate 17808084 # Simulator tick rate (ticks/s)
|
||||
host_inst_rate 48159 # Simulator instruction rate (inst/s)
|
||||
host_mem_usage 179620 # Number of bytes of host memory used
|
||||
host_seconds 0.10 # Real time elapsed on the host
|
||||
host_tick_rate 15510230 # Simulator tick rate (ticks/s)
|
||||
sim_freq 1000000000000 # Frequency of simulated ticks
|
||||
sim_insts 4483 # Number of instructions simulated
|
||||
sim_seconds 0.000001 # Number of seconds simulated
|
||||
sim_ticks 1497001 # Number of ticks simulated
|
||||
system.cpu.dcache.ReadReq_accesses 464 # number of ReadReq accesses(hits+misses)
|
||||
system.cpu.dcache.ReadReq_avg_miss_latency 3972.166667 # average ReadReq miss latency
|
||||
system.cpu.dcache.ReadReq_avg_mshr_miss_latency 2972.166667 # average ReadReq mshr miss latency
|
||||
system.cpu.dcache.ReadReq_hits 410 # number of ReadReq hits
|
||||
system.cpu.dcache.ReadReq_miss_latency 214497 # number of ReadReq miss cycles
|
||||
system.cpu.dcache.ReadReq_miss_rate 0.116379 # miss rate for ReadReq accesses
|
||||
sim_insts 4863 # Number of instructions simulated
|
||||
sim_seconds 0.000002 # Number of seconds simulated
|
||||
sim_ticks 1573001 # Number of ticks simulated
|
||||
system.cpu.dcache.ReadReq_accesses 608 # number of ReadReq accesses(hits+misses)
|
||||
system.cpu.dcache.ReadReq_avg_miss_latency 3971.370370 # average ReadReq miss latency
|
||||
system.cpu.dcache.ReadReq_avg_mshr_miss_latency 2971.370370 # average ReadReq mshr miss latency
|
||||
system.cpu.dcache.ReadReq_hits 554 # number of ReadReq hits
|
||||
system.cpu.dcache.ReadReq_miss_latency 214454 # number of ReadReq miss cycles
|
||||
system.cpu.dcache.ReadReq_miss_rate 0.088816 # miss rate for ReadReq accesses
|
||||
system.cpu.dcache.ReadReq_misses 54 # number of ReadReq misses
|
||||
system.cpu.dcache.ReadReq_mshr_miss_latency 160497 # number of ReadReq MSHR miss cycles
|
||||
system.cpu.dcache.ReadReq_mshr_miss_rate 0.116379 # mshr miss rate for ReadReq accesses
|
||||
system.cpu.dcache.ReadReq_mshr_miss_latency 160454 # number of ReadReq MSHR miss cycles
|
||||
system.cpu.dcache.ReadReq_mshr_miss_rate 0.088816 # mshr miss rate for ReadReq accesses
|
||||
system.cpu.dcache.ReadReq_mshr_misses 54 # number of ReadReq MSHR misses
|
||||
system.cpu.dcache.WriteReq_accesses 501 # number of WriteReq accesses(hits+misses)
|
||||
system.cpu.dcache.WriteReq_avg_miss_latency 3980.840580 # average WriteReq miss latency
|
||||
system.cpu.dcache.WriteReq_avg_mshr_miss_latency 2980.840580 # average WriteReq mshr miss latency
|
||||
system.cpu.dcache.WriteReq_hits 432 # number of WriteReq hits
|
||||
system.cpu.dcache.WriteReq_miss_latency 274678 # number of WriteReq miss cycles
|
||||
system.cpu.dcache.WriteReq_miss_rate 0.137725 # miss rate for WriteReq accesses
|
||||
system.cpu.dcache.WriteReq_misses 69 # number of WriteReq misses
|
||||
system.cpu.dcache.WriteReq_mshr_miss_latency 205678 # number of WriteReq MSHR miss cycles
|
||||
system.cpu.dcache.WriteReq_mshr_miss_rate 0.137725 # mshr miss rate for WriteReq accesses
|
||||
system.cpu.dcache.WriteReq_mshr_misses 69 # number of WriteReq MSHR misses
|
||||
system.cpu.dcache.WriteReq_accesses 661 # number of WriteReq accesses(hits+misses)
|
||||
system.cpu.dcache.WriteReq_avg_miss_latency 3981.559524 # average WriteReq miss latency
|
||||
system.cpu.dcache.WriteReq_avg_mshr_miss_latency 2981.559524 # average WriteReq mshr miss latency
|
||||
system.cpu.dcache.WriteReq_hits 577 # number of WriteReq hits
|
||||
system.cpu.dcache.WriteReq_miss_latency 334451 # number of WriteReq miss cycles
|
||||
system.cpu.dcache.WriteReq_miss_rate 0.127080 # miss rate for WriteReq accesses
|
||||
system.cpu.dcache.WriteReq_misses 84 # number of WriteReq misses
|
||||
system.cpu.dcache.WriteReq_mshr_miss_latency 250451 # number of WriteReq MSHR miss cycles
|
||||
system.cpu.dcache.WriteReq_mshr_miss_rate 0.127080 # mshr miss rate for WriteReq accesses
|
||||
system.cpu.dcache.WriteReq_mshr_misses 84 # number of WriteReq MSHR misses
|
||||
system.cpu.dcache.avg_blocked_cycles_no_mshrs <err: div-0> # average number of cycles each access was blocked
|
||||
system.cpu.dcache.avg_blocked_cycles_no_targets <err: div-0> # average number of cycles each access was blocked
|
||||
system.cpu.dcache.avg_refs 6.845528 # Average number of references to valid blocks.
|
||||
system.cpu.dcache.avg_refs 8.195652 # Average number of references to valid blocks.
|
||||
system.cpu.dcache.blocked_no_mshrs 0 # number of cycles access was blocked
|
||||
system.cpu.dcache.blocked_no_targets 0 # number of cycles access was blocked
|
||||
system.cpu.dcache.blocked_cycles_no_mshrs 0 # number of cycles access was blocked
|
||||
system.cpu.dcache.blocked_cycles_no_targets 0 # number of cycles access was blocked
|
||||
system.cpu.dcache.cache_copies 0 # number of cache copies performed
|
||||
system.cpu.dcache.demand_accesses 965 # number of demand (read+write) accesses
|
||||
system.cpu.dcache.demand_avg_miss_latency 3977.032520 # average overall miss latency
|
||||
system.cpu.dcache.demand_avg_mshr_miss_latency 2977.032520 # average overall mshr miss latency
|
||||
system.cpu.dcache.demand_hits 842 # number of demand (read+write) hits
|
||||
system.cpu.dcache.demand_miss_latency 489175 # number of demand (read+write) miss cycles
|
||||
system.cpu.dcache.demand_miss_rate 0.127461 # miss rate for demand accesses
|
||||
system.cpu.dcache.demand_misses 123 # number of demand (read+write) misses
|
||||
system.cpu.dcache.demand_accesses 1269 # number of demand (read+write) accesses
|
||||
system.cpu.dcache.demand_avg_miss_latency 3977.572464 # average overall miss latency
|
||||
system.cpu.dcache.demand_avg_mshr_miss_latency 2977.572464 # average overall mshr miss latency
|
||||
system.cpu.dcache.demand_hits 1131 # number of demand (read+write) hits
|
||||
system.cpu.dcache.demand_miss_latency 548905 # number of demand (read+write) miss cycles
|
||||
system.cpu.dcache.demand_miss_rate 0.108747 # miss rate for demand accesses
|
||||
system.cpu.dcache.demand_misses 138 # number of demand (read+write) misses
|
||||
system.cpu.dcache.demand_mshr_hits 0 # number of demand (read+write) MSHR hits
|
||||
system.cpu.dcache.demand_mshr_miss_latency 366175 # number of demand (read+write) MSHR miss cycles
|
||||
system.cpu.dcache.demand_mshr_miss_rate 0.127461 # mshr miss rate for demand accesses
|
||||
system.cpu.dcache.demand_mshr_misses 123 # number of demand (read+write) MSHR misses
|
||||
system.cpu.dcache.demand_mshr_miss_latency 410905 # number of demand (read+write) MSHR miss cycles
|
||||
system.cpu.dcache.demand_mshr_miss_rate 0.108747 # mshr miss rate for demand accesses
|
||||
system.cpu.dcache.demand_mshr_misses 138 # number of demand (read+write) MSHR misses
|
||||
system.cpu.dcache.fast_writes 0 # number of fast writes performed
|
||||
system.cpu.dcache.mshr_cap_events 0 # number of times MSHR cap was activated
|
||||
system.cpu.dcache.no_allocate_misses 0 # Number of misses that were no-allocate
|
||||
system.cpu.dcache.overall_accesses 965 # number of overall (read+write) accesses
|
||||
system.cpu.dcache.overall_avg_miss_latency 3977.032520 # average overall miss latency
|
||||
system.cpu.dcache.overall_avg_mshr_miss_latency 2977.032520 # average overall mshr miss latency
|
||||
system.cpu.dcache.overall_accesses 1269 # number of overall (read+write) accesses
|
||||
system.cpu.dcache.overall_avg_miss_latency 3977.572464 # average overall miss latency
|
||||
system.cpu.dcache.overall_avg_mshr_miss_latency 2977.572464 # average overall mshr miss latency
|
||||
system.cpu.dcache.overall_avg_mshr_uncacheable_latency no value # average overall mshr uncacheable latency
|
||||
system.cpu.dcache.overall_hits 842 # number of overall hits
|
||||
system.cpu.dcache.overall_miss_latency 489175 # number of overall miss cycles
|
||||
system.cpu.dcache.overall_miss_rate 0.127461 # miss rate for overall accesses
|
||||
system.cpu.dcache.overall_misses 123 # number of overall misses
|
||||
system.cpu.dcache.overall_hits 1131 # number of overall hits
|
||||
system.cpu.dcache.overall_miss_latency 548905 # number of overall miss cycles
|
||||
system.cpu.dcache.overall_miss_rate 0.108747 # miss rate for overall accesses
|
||||
system.cpu.dcache.overall_misses 138 # number of overall misses
|
||||
system.cpu.dcache.overall_mshr_hits 0 # number of overall MSHR hits
|
||||
system.cpu.dcache.overall_mshr_miss_latency 366175 # number of overall MSHR miss cycles
|
||||
system.cpu.dcache.overall_mshr_miss_rate 0.127461 # mshr miss rate for overall accesses
|
||||
system.cpu.dcache.overall_mshr_misses 123 # number of overall MSHR misses
|
||||
system.cpu.dcache.overall_mshr_miss_latency 410905 # number of overall MSHR miss cycles
|
||||
system.cpu.dcache.overall_mshr_miss_rate 0.108747 # mshr miss rate for overall accesses
|
||||
system.cpu.dcache.overall_mshr_misses 138 # number of overall MSHR misses
|
||||
system.cpu.dcache.overall_mshr_uncacheable_latency 0 # number of overall MSHR uncacheable cycles
|
||||
system.cpu.dcache.overall_mshr_uncacheable_misses 0 # number of overall MSHR uncacheable misses
|
||||
system.cpu.dcache.prefetcher.num_hwpf_already_in_cache 0 # number of hwpf that were already in the cache
|
||||
|
@ -74,56 +74,56 @@ system.cpu.dcache.prefetcher.num_hwpf_removed_MSHR_hit 0
|
|||
system.cpu.dcache.prefetcher.num_hwpf_span_page 0 # number of hwpf spanning a virtual page
|
||||
system.cpu.dcache.prefetcher.num_hwpf_squashed_from_miss 0 # number of hwpf that got squashed due to a miss aborting calculation time
|
||||
system.cpu.dcache.replacements 0 # number of replacements
|
||||
system.cpu.dcache.sampled_refs 123 # Sample count of references to valid blocks.
|
||||
system.cpu.dcache.sampled_refs 138 # Sample count of references to valid blocks.
|
||||
system.cpu.dcache.soft_prefetch_mshr_full 0 # number of mshr full events for SW prefetching instrutions
|
||||
system.cpu.dcache.tagsinuse 71.370810 # Cycle average of tags in use
|
||||
system.cpu.dcache.total_refs 842 # Total number of references to valid blocks.
|
||||
system.cpu.dcache.tagsinuse 81.997528 # Cycle average of tags in use
|
||||
system.cpu.dcache.total_refs 1131 # Total number of references to valid blocks.
|
||||
system.cpu.dcache.warmup_cycle 0 # Cycle when the warmup percentage was hit.
|
||||
system.cpu.dcache.writebacks 0 # number of writebacks
|
||||
system.cpu.icache.ReadReq_accesses 4484 # number of ReadReq accesses(hits+misses)
|
||||
system.cpu.icache.ReadReq_avg_miss_latency 3979.178571 # average ReadReq miss latency
|
||||
system.cpu.icache.ReadReq_avg_mshr_miss_latency 2979.178571 # average ReadReq mshr miss latency
|
||||
system.cpu.icache.ReadReq_hits 4232 # number of ReadReq hits
|
||||
system.cpu.icache.ReadReq_miss_latency 1002753 # number of ReadReq miss cycles
|
||||
system.cpu.icache.ReadReq_miss_rate 0.056200 # miss rate for ReadReq accesses
|
||||
system.cpu.icache.ReadReq_misses 252 # number of ReadReq misses
|
||||
system.cpu.icache.ReadReq_mshr_miss_latency 750753 # number of ReadReq MSHR miss cycles
|
||||
system.cpu.icache.ReadReq_mshr_miss_rate 0.056200 # mshr miss rate for ReadReq accesses
|
||||
system.cpu.icache.ReadReq_mshr_misses 252 # number of ReadReq MSHR misses
|
||||
system.cpu.icache.ReadReq_accesses 4864 # number of ReadReq accesses(hits+misses)
|
||||
system.cpu.icache.ReadReq_avg_miss_latency 3977.960938 # average ReadReq miss latency
|
||||
system.cpu.icache.ReadReq_avg_mshr_miss_latency 2977.960938 # average ReadReq mshr miss latency
|
||||
system.cpu.icache.ReadReq_hits 4608 # number of ReadReq hits
|
||||
system.cpu.icache.ReadReq_miss_latency 1018358 # number of ReadReq miss cycles
|
||||
system.cpu.icache.ReadReq_miss_rate 0.052632 # miss rate for ReadReq accesses
|
||||
system.cpu.icache.ReadReq_misses 256 # number of ReadReq misses
|
||||
system.cpu.icache.ReadReq_mshr_miss_latency 762358 # number of ReadReq MSHR miss cycles
|
||||
system.cpu.icache.ReadReq_mshr_miss_rate 0.052632 # mshr miss rate for ReadReq accesses
|
||||
system.cpu.icache.ReadReq_mshr_misses 256 # number of ReadReq MSHR misses
|
||||
system.cpu.icache.avg_blocked_cycles_no_mshrs <err: div-0> # average number of cycles each access was blocked
|
||||
system.cpu.icache.avg_blocked_cycles_no_targets <err: div-0> # average number of cycles each access was blocked
|
||||
system.cpu.icache.avg_refs 16.793651 # Average number of references to valid blocks.
|
||||
system.cpu.icache.avg_refs 18 # Average number of references to valid blocks.
|
||||
system.cpu.icache.blocked_no_mshrs 0 # number of cycles access was blocked
|
||||
system.cpu.icache.blocked_no_targets 0 # number of cycles access was blocked
|
||||
system.cpu.icache.blocked_cycles_no_mshrs 0 # number of cycles access was blocked
|
||||
system.cpu.icache.blocked_cycles_no_targets 0 # number of cycles access was blocked
|
||||
system.cpu.icache.cache_copies 0 # number of cache copies performed
|
||||
system.cpu.icache.demand_accesses 4484 # number of demand (read+write) accesses
|
||||
system.cpu.icache.demand_avg_miss_latency 3979.178571 # average overall miss latency
|
||||
system.cpu.icache.demand_avg_mshr_miss_latency 2979.178571 # average overall mshr miss latency
|
||||
system.cpu.icache.demand_hits 4232 # number of demand (read+write) hits
|
||||
system.cpu.icache.demand_miss_latency 1002753 # number of demand (read+write) miss cycles
|
||||
system.cpu.icache.demand_miss_rate 0.056200 # miss rate for demand accesses
|
||||
system.cpu.icache.demand_misses 252 # number of demand (read+write) misses
|
||||
system.cpu.icache.demand_accesses 4864 # number of demand (read+write) accesses
|
||||
system.cpu.icache.demand_avg_miss_latency 3977.960938 # average overall miss latency
|
||||
system.cpu.icache.demand_avg_mshr_miss_latency 2977.960938 # average overall mshr miss latency
|
||||
system.cpu.icache.demand_hits 4608 # number of demand (read+write) hits
|
||||
system.cpu.icache.demand_miss_latency 1018358 # number of demand (read+write) miss cycles
|
||||
system.cpu.icache.demand_miss_rate 0.052632 # miss rate for demand accesses
|
||||
system.cpu.icache.demand_misses 256 # number of demand (read+write) misses
|
||||
system.cpu.icache.demand_mshr_hits 0 # number of demand (read+write) MSHR hits
|
||||
system.cpu.icache.demand_mshr_miss_latency 750753 # number of demand (read+write) MSHR miss cycles
|
||||
system.cpu.icache.demand_mshr_miss_rate 0.056200 # mshr miss rate for demand accesses
|
||||
system.cpu.icache.demand_mshr_misses 252 # number of demand (read+write) MSHR misses
|
||||
system.cpu.icache.demand_mshr_miss_latency 762358 # number of demand (read+write) MSHR miss cycles
|
||||
system.cpu.icache.demand_mshr_miss_rate 0.052632 # mshr miss rate for demand accesses
|
||||
system.cpu.icache.demand_mshr_misses 256 # number of demand (read+write) MSHR misses
|
||||
system.cpu.icache.fast_writes 0 # number of fast writes performed
|
||||
system.cpu.icache.mshr_cap_events 0 # number of times MSHR cap was activated
|
||||
system.cpu.icache.no_allocate_misses 0 # Number of misses that were no-allocate
|
||||
system.cpu.icache.overall_accesses 4484 # number of overall (read+write) accesses
|
||||
system.cpu.icache.overall_avg_miss_latency 3979.178571 # average overall miss latency
|
||||
system.cpu.icache.overall_avg_mshr_miss_latency 2979.178571 # average overall mshr miss latency
|
||||
system.cpu.icache.overall_accesses 4864 # number of overall (read+write) accesses
|
||||
system.cpu.icache.overall_avg_miss_latency 3977.960938 # average overall miss latency
|
||||
system.cpu.icache.overall_avg_mshr_miss_latency 2977.960938 # average overall mshr miss latency
|
||||
system.cpu.icache.overall_avg_mshr_uncacheable_latency no value # average overall mshr uncacheable latency
|
||||
system.cpu.icache.overall_hits 4232 # number of overall hits
|
||||
system.cpu.icache.overall_miss_latency 1002753 # number of overall miss cycles
|
||||
system.cpu.icache.overall_miss_rate 0.056200 # miss rate for overall accesses
|
||||
system.cpu.icache.overall_misses 252 # number of overall misses
|
||||
system.cpu.icache.overall_hits 4608 # number of overall hits
|
||||
system.cpu.icache.overall_miss_latency 1018358 # number of overall miss cycles
|
||||
system.cpu.icache.overall_miss_rate 0.052632 # miss rate for overall accesses
|
||||
system.cpu.icache.overall_misses 256 # number of overall misses
|
||||
system.cpu.icache.overall_mshr_hits 0 # number of overall MSHR hits
|
||||
system.cpu.icache.overall_mshr_miss_latency 750753 # number of overall MSHR miss cycles
|
||||
system.cpu.icache.overall_mshr_miss_rate 0.056200 # mshr miss rate for overall accesses
|
||||
system.cpu.icache.overall_mshr_misses 252 # number of overall MSHR misses
|
||||
system.cpu.icache.overall_mshr_miss_latency 762358 # number of overall MSHR miss cycles
|
||||
system.cpu.icache.overall_mshr_miss_rate 0.052632 # mshr miss rate for overall accesses
|
||||
system.cpu.icache.overall_mshr_misses 256 # number of overall MSHR misses
|
||||
system.cpu.icache.overall_mshr_uncacheable_latency 0 # number of overall MSHR uncacheable cycles
|
||||
system.cpu.icache.overall_mshr_uncacheable_misses 0 # number of overall MSHR uncacheable misses
|
||||
system.cpu.icache.prefetcher.num_hwpf_already_in_cache 0 # number of hwpf that were already in the cache
|
||||
|
@ -136,57 +136,57 @@ system.cpu.icache.prefetcher.num_hwpf_removed_MSHR_hit 0
|
|||
system.cpu.icache.prefetcher.num_hwpf_span_page 0 # number of hwpf spanning a virtual page
|
||||
system.cpu.icache.prefetcher.num_hwpf_squashed_from_miss 0 # number of hwpf that got squashed due to a miss aborting calculation time
|
||||
system.cpu.icache.replacements 0 # number of replacements
|
||||
system.cpu.icache.sampled_refs 252 # Sample count of references to valid blocks.
|
||||
system.cpu.icache.sampled_refs 256 # Sample count of references to valid blocks.
|
||||
system.cpu.icache.soft_prefetch_mshr_full 0 # number of mshr full events for SW prefetching instrutions
|
||||
system.cpu.icache.tagsinuse 115.914677 # Cycle average of tags in use
|
||||
system.cpu.icache.total_refs 4232 # Total number of references to valid blocks.
|
||||
system.cpu.icache.tagsinuse 114.778311 # Cycle average of tags in use
|
||||
system.cpu.icache.total_refs 4608 # Total number of references to valid blocks.
|
||||
system.cpu.icache.warmup_cycle 0 # Cycle when the warmup percentage was hit.
|
||||
system.cpu.icache.writebacks 0 # number of writebacks
|
||||
system.cpu.idle_fraction 0 # Percentage of idle cycles
|
||||
system.cpu.l2cache.ReadReq_accesses 375 # number of ReadReq accesses(hits+misses)
|
||||
system.cpu.l2cache.ReadReq_avg_miss_latency 2986.473118 # average ReadReq miss latency
|
||||
system.cpu.l2cache.ReadReq_avg_mshr_miss_latency 1985.473118 # average ReadReq mshr miss latency
|
||||
system.cpu.l2cache.ReadReq_accesses 394 # number of ReadReq accesses(hits+misses)
|
||||
system.cpu.l2cache.ReadReq_avg_miss_latency 2985.429668 # average ReadReq miss latency
|
||||
system.cpu.l2cache.ReadReq_avg_mshr_miss_latency 1984.429668 # average ReadReq mshr miss latency
|
||||
system.cpu.l2cache.ReadReq_hits 3 # number of ReadReq hits
|
||||
system.cpu.l2cache.ReadReq_miss_latency 1110968 # number of ReadReq miss cycles
|
||||
system.cpu.l2cache.ReadReq_miss_rate 0.992000 # miss rate for ReadReq accesses
|
||||
system.cpu.l2cache.ReadReq_misses 372 # number of ReadReq misses
|
||||
system.cpu.l2cache.ReadReq_mshr_miss_latency 738596 # number of ReadReq MSHR miss cycles
|
||||
system.cpu.l2cache.ReadReq_mshr_miss_rate 0.992000 # mshr miss rate for ReadReq accesses
|
||||
system.cpu.l2cache.ReadReq_mshr_misses 372 # number of ReadReq MSHR misses
|
||||
system.cpu.l2cache.ReadReq_miss_latency 1167303 # number of ReadReq miss cycles
|
||||
system.cpu.l2cache.ReadReq_miss_rate 0.992386 # miss rate for ReadReq accesses
|
||||
system.cpu.l2cache.ReadReq_misses 391 # number of ReadReq misses
|
||||
system.cpu.l2cache.ReadReq_mshr_miss_latency 775912 # number of ReadReq MSHR miss cycles
|
||||
system.cpu.l2cache.ReadReq_mshr_miss_rate 0.992386 # mshr miss rate for ReadReq accesses
|
||||
system.cpu.l2cache.ReadReq_mshr_misses 391 # number of ReadReq MSHR misses
|
||||
system.cpu.l2cache.avg_blocked_cycles_no_mshrs <err: div-0> # average number of cycles each access was blocked
|
||||
system.cpu.l2cache.avg_blocked_cycles_no_targets <err: div-0> # average number of cycles each access was blocked
|
||||
system.cpu.l2cache.avg_refs 0.008065 # Average number of references to valid blocks.
|
||||
system.cpu.l2cache.avg_refs 0.007673 # Average number of references to valid blocks.
|
||||
system.cpu.l2cache.blocked_no_mshrs 0 # number of cycles access was blocked
|
||||
system.cpu.l2cache.blocked_no_targets 0 # number of cycles access was blocked
|
||||
system.cpu.l2cache.blocked_cycles_no_mshrs 0 # number of cycles access was blocked
|
||||
system.cpu.l2cache.blocked_cycles_no_targets 0 # number of cycles access was blocked
|
||||
system.cpu.l2cache.cache_copies 0 # number of cache copies performed
|
||||
system.cpu.l2cache.demand_accesses 375 # number of demand (read+write) accesses
|
||||
system.cpu.l2cache.demand_avg_miss_latency 2986.473118 # average overall miss latency
|
||||
system.cpu.l2cache.demand_avg_mshr_miss_latency 1985.473118 # average overall mshr miss latency
|
||||
system.cpu.l2cache.demand_accesses 394 # number of demand (read+write) accesses
|
||||
system.cpu.l2cache.demand_avg_miss_latency 2985.429668 # average overall miss latency
|
||||
system.cpu.l2cache.demand_avg_mshr_miss_latency 1984.429668 # average overall mshr miss latency
|
||||
system.cpu.l2cache.demand_hits 3 # number of demand (read+write) hits
|
||||
system.cpu.l2cache.demand_miss_latency 1110968 # number of demand (read+write) miss cycles
|
||||
system.cpu.l2cache.demand_miss_rate 0.992000 # miss rate for demand accesses
|
||||
system.cpu.l2cache.demand_misses 372 # number of demand (read+write) misses
|
||||
system.cpu.l2cache.demand_miss_latency 1167303 # number of demand (read+write) miss cycles
|
||||
system.cpu.l2cache.demand_miss_rate 0.992386 # miss rate for demand accesses
|
||||
system.cpu.l2cache.demand_misses 391 # number of demand (read+write) misses
|
||||
system.cpu.l2cache.demand_mshr_hits 0 # number of demand (read+write) MSHR hits
|
||||
system.cpu.l2cache.demand_mshr_miss_latency 738596 # number of demand (read+write) MSHR miss cycles
|
||||
system.cpu.l2cache.demand_mshr_miss_rate 0.992000 # mshr miss rate for demand accesses
|
||||
system.cpu.l2cache.demand_mshr_misses 372 # number of demand (read+write) MSHR misses
|
||||
system.cpu.l2cache.demand_mshr_miss_latency 775912 # number of demand (read+write) MSHR miss cycles
|
||||
system.cpu.l2cache.demand_mshr_miss_rate 0.992386 # mshr miss rate for demand accesses
|
||||
system.cpu.l2cache.demand_mshr_misses 391 # number of demand (read+write) MSHR misses
|
||||
system.cpu.l2cache.fast_writes 0 # number of fast writes performed
|
||||
system.cpu.l2cache.mshr_cap_events 0 # number of times MSHR cap was activated
|
||||
system.cpu.l2cache.no_allocate_misses 0 # Number of misses that were no-allocate
|
||||
system.cpu.l2cache.overall_accesses 375 # number of overall (read+write) accesses
|
||||
system.cpu.l2cache.overall_avg_miss_latency 2986.473118 # average overall miss latency
|
||||
system.cpu.l2cache.overall_avg_mshr_miss_latency 1985.473118 # average overall mshr miss latency
|
||||
system.cpu.l2cache.overall_accesses 394 # number of overall (read+write) accesses
|
||||
system.cpu.l2cache.overall_avg_miss_latency 2985.429668 # average overall miss latency
|
||||
system.cpu.l2cache.overall_avg_mshr_miss_latency 1984.429668 # average overall mshr miss latency
|
||||
system.cpu.l2cache.overall_avg_mshr_uncacheable_latency no value # average overall mshr uncacheable latency
|
||||
system.cpu.l2cache.overall_hits 3 # number of overall hits
|
||||
system.cpu.l2cache.overall_miss_latency 1110968 # number of overall miss cycles
|
||||
system.cpu.l2cache.overall_miss_rate 0.992000 # miss rate for overall accesses
|
||||
system.cpu.l2cache.overall_misses 372 # number of overall misses
|
||||
system.cpu.l2cache.overall_miss_latency 1167303 # number of overall miss cycles
|
||||
system.cpu.l2cache.overall_miss_rate 0.992386 # miss rate for overall accesses
|
||||
system.cpu.l2cache.overall_misses 391 # number of overall misses
|
||||
system.cpu.l2cache.overall_mshr_hits 0 # number of overall MSHR hits
|
||||
system.cpu.l2cache.overall_mshr_miss_latency 738596 # number of overall MSHR miss cycles
|
||||
system.cpu.l2cache.overall_mshr_miss_rate 0.992000 # mshr miss rate for overall accesses
|
||||
system.cpu.l2cache.overall_mshr_misses 372 # number of overall MSHR misses
|
||||
system.cpu.l2cache.overall_mshr_miss_latency 775912 # number of overall MSHR miss cycles
|
||||
system.cpu.l2cache.overall_mshr_miss_rate 0.992386 # mshr miss rate for overall accesses
|
||||
system.cpu.l2cache.overall_mshr_misses 391 # number of overall MSHR misses
|
||||
system.cpu.l2cache.overall_mshr_uncacheable_latency 0 # number of overall MSHR uncacheable cycles
|
||||
system.cpu.l2cache.overall_mshr_uncacheable_misses 0 # number of overall MSHR uncacheable misses
|
||||
system.cpu.l2cache.prefetcher.num_hwpf_already_in_cache 0 # number of hwpf that were already in the cache
|
||||
|
@ -199,16 +199,16 @@ system.cpu.l2cache.prefetcher.num_hwpf_removed_MSHR_hit 0
|
|||
system.cpu.l2cache.prefetcher.num_hwpf_span_page 0 # number of hwpf spanning a virtual page
|
||||
system.cpu.l2cache.prefetcher.num_hwpf_squashed_from_miss 0 # number of hwpf that got squashed due to a miss aborting calculation time
|
||||
system.cpu.l2cache.replacements 0 # number of replacements
|
||||
system.cpu.l2cache.sampled_refs 372 # Sample count of references to valid blocks.
|
||||
system.cpu.l2cache.sampled_refs 391 # Sample count of references to valid blocks.
|
||||
system.cpu.l2cache.soft_prefetch_mshr_full 0 # number of mshr full events for SW prefetching instrutions
|
||||
system.cpu.l2cache.tagsinuse 185.896040 # Cycle average of tags in use
|
||||
system.cpu.l2cache.tagsinuse 195.424915 # Cycle average of tags in use
|
||||
system.cpu.l2cache.total_refs 3 # Total number of references to valid blocks.
|
||||
system.cpu.l2cache.warmup_cycle 0 # Cycle when the warmup percentage was hit.
|
||||
system.cpu.l2cache.writebacks 0 # number of writebacks
|
||||
system.cpu.not_idle_fraction 1 # Percentage of non-idle cycles
|
||||
system.cpu.numCycles 1497001 # number of cpu cycles simulated
|
||||
system.cpu.num_insts 4483 # Number of instructions executed
|
||||
system.cpu.num_refs 965 # Number of memory references
|
||||
system.cpu.numCycles 1573001 # number of cpu cycles simulated
|
||||
system.cpu.num_insts 4863 # Number of instructions executed
|
||||
system.cpu.num_refs 1269 # Number of memory references
|
||||
system.cpu.workload.PROG:num_syscalls 11 # Number of system calls
|
||||
|
||||
---------- End Simulation Statistics ----------
|
||||
|
|
|
@ -5,8 +5,8 @@ The Regents of The University of Michigan
|
|||
All Rights Reserved
|
||||
|
||||
|
||||
M5 compiled Oct 23 2006 07:47:36
|
||||
M5 started Mon Oct 23 07:47:41 2006
|
||||
M5 executing on zeep
|
||||
M5 compiled Oct 27 2006 02:07:29
|
||||
M5 started Fri Oct 27 02:08:11 2006
|
||||
M5 executing on zizzer.eecs.umich.edu
|
||||
command line: build/SPARC_SE/m5.debug -d build/SPARC_SE/tests/debug/quick/00.hello/sparc/linux/simple-timing tests/run.py quick/00.hello/sparc/linux/simple-timing
|
||||
Exiting @ tick 1497001 because target called exit()
|
||||
Exiting @ tick 1573001 because target called exit()
|
||||
|
|
Loading…
Reference in a new issue