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

into  doughnut.mwconnections.com:/home/gblack/m5/newmem-x86

--HG--
extra : convert_revision : 3f17fc418ee5a30da2b08a515fb394cc8fcdd237
This commit is contained in:
Gabe Black 2007-05-18 13:36:47 -07:00
commit a13d5af274
326 changed files with 11046 additions and 19403 deletions

View file

@ -29,13 +29,13 @@ Steven K. Reinhardt
Ali G. Saidi
-----------------------
* SPARC Full System Support
* Alpha Linux support
* Alpha (Tsunami) platform and devices
* I/O <-> memory interface
* PCI device interface
* Multiple ISA support
* Memory bridge, bus, packet, port interfaces
* SPARC IPRs
Kevin T. Lim
-----------------------

View file

@ -1,3 +1,37 @@
Outstanding issues for 2.0 release:
--------------------
1. Fix multi-level coherence/dma issues
2. Fix O3 CPU bug in SE 40.perlbmk fails
3. Fix O3 processing nacks/coherence messages
4. Better statistics for the caches.
5. Clean up more SimObject parameter stuff
6. Checkpoint/switchover testing
7. FS mode doesn't work under Cygwin
8. memtest regression crashes under Cygwin
9. Make repository public
10. Testing
11. Validation
12. Testing
May 16, 2007: m5_2.0_beta3
--------------------
New Features
1. Some support for SPARC full-system simulation
2. Reworking of trace facitities (parameter names changed, variadic macros
removed)
3. Scons script cleanups
4. Some support for compiling with Intel CC
Bug fixes since beta 2:
1. Many SPARC linux syscall emulation support fixes
2. Multiprocessor linux boot using the detailed O3 CPU module
3. Workaround for DMA bug (final solution to be released with 2.0f)
4. Simulator performance and memory leak fixes
5. Fixed issue where console could stop printing in ALPHA_FS
6. Fix issues with remote debugging
7. Several compile fixes, including gcc 4.1
8. Many other minor fixes and enhancements
Nov. 28, 2006: m5_2.0_beta2
--------------------
Bug fixes since beta 1:
@ -7,13 +41,9 @@ Bug fixes since beta 1:
4. Draining/Switchover
5. Functional Accesses
6. Bus now has real timing
7. Single config file fro all SpecCPU2000 benchmarks
7. Single config file for all SpecCPU2000 benchmarks
8. Several other minor bug fixes and enhancements
Outstading issues for 2.0 release:
1. Simulator performance fixes for memory system/caches
2. Multiprocessor linux boot using the detailed O3 CPU model
Aug. 25, 2006: m5_2.0_beta patch 1
--------------------
Handful of minor bug fixes for m5_2.0_beta,

View file

@ -1,7 +1,4 @@
echo "switching cpus"
m5 switchcpu
echo "done"
insmod /modules/devtime.ko dataAddr=0x9000004 count=100
insmod /modules/devtime.ko dataAddr=0x9000008 count=100
rmmod devtime
insmod /modules/devtime.ko dataAddr=0x1a0000300 count=100
rmmod devtime

View file

@ -1,6 +1,6 @@
#!/bin/sh
cd /benchmarks/tests
cd /benchmarks
/sbin/m5 resetstats
./pthread_mutex_test 4 10000
/sbin/m5 exit

View file

@ -0,0 +1,45 @@
#!/bin/sh
SERVER=10.0.0.1
CLIENT=10.0.0.2
echo "setting up network..."
ifconfig lo 127.0.0.1
ifconfig eth0 $CLIENT txqueuelen 1000
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
echo "262143" > /proc/sys/net/core/rmem_max
echo "262143" > /proc/sys/net/core/wmem_max
echo "262143" > /proc/sys/net/core/rmem_default
echo "262143" > /proc/sys/net/core/wmem_default
echo "262143" > /proc/sys/net/core/optmem_max
echo "100000" > /proc/sys/net/core/netdev_max_backlog
echo -n "waiting for server..."
netcat -c -l -p 8000
BINARY=/benchmarks/netperf-bin/netperf
TEST="UDP_STREAM"
SHORT_ARGS="-l 2 -- -m 16384 -M 16384 -s 262144 -S 262144"
#LONG_ARGS="-k16384,0 -K16384,0 -- -m 65536 -M 65536 -s 262144 -S 262144"
SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS"
LONG="$BINARY -H $SERVER -t $TEST $LONG_ARGS"
echo "starting test..."
echo "netperf warmup"
echo $SHORT
eval $SHORT
#echo "netperf benchmark"
#echo $LONG
#/sbin/m5 ivlb 1
#/sbin/m5 resetstats
#/sbin/m5 dumpresetstats 200000000 2000000000
#/sbin/m5 checkpoint 200000000 2000000000
#eval $LONG
/sbin/m5 exit

View file

@ -0,0 +1,22 @@
#!/bin/sh
SERVER=127.0.0.1
CLIENT=127.0.0.1
echo "setting up network..."
ifconfig lo 127.0.0.1
BINARY=/benchmarks/netperf-bin/netperf
TEST="UDP_STREAM"
SHORT_ARGS="-l 2 -- -m 4096"
echo "running netserver..."
/benchmarks/netperf-bin/netserver
SHORT="$BINARY -H $SERVER -t $TEST $SHORT_ARGS"
echo "starting test..."
echo $SHORT
eval $SHORT
/sbin/m5 exit

View file

@ -21,5 +21,5 @@ echo "100000" > /proc/sys/net/core/netdev_max_backlog
echo -n "waiting for server..."
netcat -c -l -p 8000
ping $SERVER
ping -c 5 $SERVER
/sbin/m5 exit

View file

@ -35,7 +35,7 @@ echo "waiting for server..."
netcat -c -l -p 8000
echo -n "running surge client..."
/bin/bash -c "cd /benchmarks/specsurge && ./spec-m5 1 20 1 192.168.0.1 5 40000 1000000000 1000"
/bin/bash -c "cd /benchmarks/surge && ./spec-m5 1 20 1 192.168.0.1 5 40000 1000000000 1000"
echo "done."
echo -n "halting machine"

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -61,6 +61,9 @@ Benchmarks = {
'NetperfStream': [SysConfig('netperf-stream-client.rcS'),
SysConfig('netperf-server.rcS')],
'NetperfStreamUdp': [SysConfig('netperf-stream-udp-client.rcS'),
SysConfig('netperf-server.rcS')],
'NetperfUdpLocal': [SysConfig('netperf-stream-udp-local.rcS')],
'NetperfStreamNT': [SysConfig('netperf-stream-nt-client.rcS'),
SysConfig('netperf-server.rcS')],
'NetperfMaerts': [SysConfig('netperf-maerts-client.rcS'),

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -32,7 +32,7 @@ from m5.objects import *
class L1Cache(BaseCache):
assoc = 2
block_size = 64
latency = 1
latency = '1ns'
mshrs = 10
tgts_per_mshr = 5
protocol = CoherenceProtocol(protocol='moesi')
@ -40,7 +40,7 @@ class L1Cache(BaseCache):
class L2Cache(BaseCache):
assoc = 8
block_size = 64
latency = 10
latency = '10ns'
mshrs = 20
tgts_per_mshr = 12

View file

@ -61,7 +61,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
self.readfile = mdesc.script()
self.iobus = Bus(bus_id=0)
self.membus = Bus(bus_id=1)
self.bridge = Bridge()
self.bridge = Bridge(fix_partial_write_b=True, delay='50ns', nack_delay='4ns')
self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
self.bridge.side_a = self.iobus.port
self.bridge.side_b = self.membus.port
@ -94,7 +94,7 @@ def makeSparcSystem(mem_mode, mdesc = None):
self.readfile = mdesc.script()
self.iobus = Bus(bus_id=0)
self.membus = Bus(bus_id=1)
self.bridge = Bridge()
self.bridge = Bridge(fix_partial_write_b=True, delay='50ns', nack_delay='4ns')
self.t1000 = T1000()
self.t1000.attachOnChipIO(self.membus)
self.t1000.attachIO(self.iobus)

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -31,6 +31,7 @@ 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")
parser.add_option("--l2cache", action="store_true")
# Run duration options
parser.add_option("-m", "--maxtick", type="int")

View file

@ -51,7 +51,6 @@ parser.add_option("--kernel", action="store", type="string")
parser.add_option("--script", action="store", type="string")
# Benchmark options
parser.add_option("--l2cache", action="store_true")
parser.add_option("--dual", action="store_true",
help="Simulate two systems attached with an ethernet link")
parser.add_option("-b", "--benchmark", action="store", type="string",

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -104,7 +104,14 @@ for i in xrange(np):
if options.caches:
system.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
L1Cache(size = '64kB'))
system.cpu[i].connectMemPorts(system.membus)
if options.l2cache:
system.l2 = L2Cache(size='2MB')
system.tol2bus = Bus()
system.l2.cpu_side = system.tol2bus.port
system.l2.mem_side = system.membus.port
system.cpu[i].connectMemPorts(system.tol2bus)
else:
system.cpu[i].connectMemPorts(system.membus)
system.cpu[i].workload = process
root = Root(system = system)

View file

@ -1,4 +1,4 @@
# Copyright (c) 2005-2006 The Regents of The University of Michigan
# Copyright (c) 2005-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -60,7 +60,7 @@ parser.add_option("--l2size",
parser.add_option("--l2latency",
default = 10)
parser.add_option("--rootdir",
help="ROot directory of Splash2",
help="Root directory of Splash2",
default="/dist/splash2/codes")
parser.add_option("-b", "--benchmark",
help="Splash 2 benchmark to run")
@ -79,59 +79,79 @@ if not options.numcpus:
# Define Splash2 Benchmarks
# ====================
class Cholesky(LiveProcess):
executable = options.rootdir + '/kernels/cholesky/CHOLESKY'
cmd = 'CHOLESKY -p' + str(options.numcpus) + ' '\
+ options.rootdir + '/kernels/cholesky/inputs/tk23.O'
cwd = options.rootdir + '/kernels/cholesky'
executable = options.rootdir + '/kernels/cholesky/CHOLESKY'
cmd = 'CHOLESKY -p' + str(options.numcpus) + ' '\
+ options.rootdir + '/kernels/cholesky/inputs/tk23.O'
class FFT(LiveProcess):
executable = options.rootdir + '/kernels/fft/FFT'
cmd = 'FFT -p' + str(options.numcpus) + ' -m18'
cwd = options.rootdir + '/kernels/fft'
executable = options.rootdir + '/kernels/fft/FFT'
cmd = 'FFT -p' + str(options.numcpus) + ' -m18'
class LU_contig(LiveProcess):
executable = options.rootdir + '/kernels/lu/contiguous_blocks/LU'
cmd = 'LU -p' + str(options.numcpus)
executable = options.rootdir + '/kernels/lu/contiguous_blocks/LU'
cmd = 'LU -p' + str(options.numcpus)
cwd = options.rootdir + '/kernels/lu/contiguous_blocks'
class LU_noncontig(LiveProcess):
executable = options.rootdir + '/kernels/lu/non_contiguous_blocks/LU'
cmd = 'LU -p' + str(options.numcpus)
executable = options.rootdir + '/kernels/lu/non_contiguous_blocks/LU'
cmd = 'LU -p' + str(options.numcpus)
cwd = options.rootdir + '/kernels/lu/non_contiguous_blocks'
class Radix(LiveProcess):
executable = options.rootdir + '/kernels/radix/RADIX'
cmd = 'RADIX -n524288 -p' + str(options.numcpus)
executable = options.rootdir + '/kernels/radix/RADIX'
cmd = 'RADIX -n524288 -p' + str(options.numcpus)
cwd = options.rootdir + '/kernels/radix'
class Barnes(LiveProcess):
executable = options.rootdir + '/apps/barnes/BARNES'
cmd = 'BARNES'
input = options.rootdir + '/apps/barnes/input.p' + str(options.numcpus)
executable = options.rootdir + '/apps/barnes/BARNES'
cmd = 'BARNES'
input = options.rootdir + '/apps/barnes/input.p' + str(options.numcpus)
cwd = options.rootdir + '/apps/barnes'
class FMM(LiveProcess):
executable = options.rootdir + '/apps/fmm/FMM'
cmd = 'FMM'
executable = options.rootdir + '/apps/fmm/FMM'
cmd = 'FMM'
if str(options.numcpus) == '1':
input = options.rootdir + '/apps/fmm/inputs/input.2048'
else:
input = options.rootdir + '/apps/fmm/inputs/input.2048.p' + str(options.numcpus)
cwd = options.rootdir + '/apps/fmm'
class Ocean_contig(LiveProcess):
executable = options.rootdir + '/apps/ocean/contiguous_partitions/OCEAN'
cmd = 'OCEAN -p' + str(options.numcpus)
executable = options.rootdir + '/apps/ocean/contiguous_partitions/OCEAN'
cmd = 'OCEAN -p' + str(options.numcpus)
cwd = options.rootdir + '/apps/ocean/contiguous_partitions'
class Ocean_noncontig(LiveProcess):
executable = options.rootdir + '/apps/ocean/non_contiguous_partitions/OCEAN'
cmd = 'OCEAN -p' + str(options.numcpus)
executable = options.rootdir + '/apps/ocean/non_contiguous_partitions/OCEAN'
cmd = 'OCEAN -p' + str(options.numcpus)
cwd = options.rootdir + '/apps/ocean/non_contiguous_partitions'
class Raytrace(LiveProcess):
executable = options.rootdir + '/apps/raytrace/RAYTRACE'
cmd = 'RAYTRACE -p' + str(options.numcpus) + ' ' \
+ options.rootdir + 'apps/raytrace/inputs/teapot.env'
executable = options.rootdir + '/apps/raytrace/RAYTRACE'
cmd = 'RAYTRACE -p' + str(options.numcpus) + ' ' \
+ options.rootdir + '/apps/raytrace/inputs/teapot.env'
cwd = options.rootdir + '/apps/raytrace'
class Water_nsquared(LiveProcess):
executable = options.rootdir + '/apps/water-nsquared/WATER-NSQUARED'
cmd = 'WATER-NSQUARED'
executable = options.rootdir + '/apps/water-nsquared/WATER-NSQUARED'
cmd = 'WATER-NSQUARED'
if options.numcpus==1:
input = options.rootdir + '/apps/water-nsquared/input'
else:
input = options.rootdir + '/apps/water-nsquared/input.p' + str(options.numcpus)
cwd = options.rootdir + '/apps/water-nsquared'
class Water_spatial(LiveProcess):
executable = options.rootdir + '/apps/water-spatial/WATER-SPATIAL'
cmd = 'WATER-SPATIAL'
executable = options.rootdir + '/apps/water-spatial/WATER-SPATIAL'
cmd = 'WATER-SPATIAL'
if options.numcpus==1:
input = options.rootdir + '/apps/water-spatial/input'
else:
input = options.rootdir + '/apps/water-spatial/input.p' + str(options.numcpus)
cwd = options.rootdir + '/apps/water-spatial'
# --------------------
# Base L1 Cache Definition

View file

@ -30,28 +30,71 @@
import os
import sys
import zipfile
from os.path import basename
from os.path import join as joinpath
import SCons
# This file defines how to build a particular configuration of M5
# based on variable settings in the 'env' build environment.
Import('*')
sources = []
def Source(*args):
for arg in args:
if isinstance(arg, (list, tuple)):
# Recurse to load a list
Source(*arg)
elif isinstance(arg, str):
sources.extend([ File(f) for f in Split(arg) ])
else:
sources.append(File(arg))
# Children need to see the environment
Export('env')
########################################################################
# Code for adding source files
#
sources = []
def Source(source):
if isinstance(source, SCons.Node.FS.File):
sources.append(source)
else:
sources.append(File(source))
# Children should have access
Export('Source')
########################################################################
# Code for adding python objects
#
py_sources = []
py_source_packages = {}
def PySource(package, source):
if not isinstance(source, SCons.Node.FS.File):
source = File(source)
py_source_packages[source] = package
py_sources.append(source)
sim_objects = []
def SimObject(source):
if not isinstance(source, SCons.Node.FS.File):
source = File(source)
PySource('m5.objects', source)
modname = basename(str(source))
sim_objects.append(modname)
swig_sources = []
swig_source_packages = {}
def SwigSource(package, source):
if not isinstance(source, SCons.Node.FS.File):
source = File(source)
swig_source_packages[source] = package
swig_sources.append(source)
# Children should have access
Export('PySource')
Export('SimObject')
Export('SwigSource')
########################################################################
#
# Set some compiler variables
#
# Include file paths are rooted in this directory. SCons will
# automatically expand '.' to refer to both the source directory and
# the corresponding build directory to pick up generated include
@ -61,7 +104,9 @@ env.Append(CPPPATH=Dir('.'))
# Add a flag defining what THE_ISA should be for all compilation
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
########################################################################
# Walk the tree and execute all SConscripts
#
scripts = []
srcdir = env['SRCDIR']
for root, dirs, files in os.walk(srcdir, topdown=True):
@ -78,6 +123,132 @@ for root, dirs, files in os.walk(srcdir, topdown=True):
for opt in env.ExportOptions:
env.ConfigFile(opt)
########################################################################
#
# Deal with python/swig, object code. Collect .py files and
# generating a zip archive that is appended to the m5 binary.
#
# Generate Python file that contains a dict specifying the current
# build_env flags.
def MakeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
print >>f, "m5_build_env = ", source[0]
f.close()
optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
env.Command('python/m5/defines.py', Value(optionDict), MakeDefinesPyFile)
PySource('m5', 'python/m5/defines.py')
def MakeInfoPyFile(target, source, env):
f = file(str(target[0]), 'w')
for src in source:
data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
print >>f, "%s = %s" % (src, repr(data))
f.close()
env.Command('python/m5/info.py',
[ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
MakeInfoPyFile)
PySource('m5', 'python/m5/info.py')
def MakeObjectsInitFile(target, source, env):
f = file(str(target[0]), 'w')
print >>f, 'from m5.SimObject import *'
for src_path in source:
src_file = basename(src_path.get_contents())
assert(src_file.endswith('.py'))
src_module = src_file[:-3]
print >>f, 'from %s import *' % src_module
f.close()
env.Command('python/m5/objects/__init__.py',
[ Value(o) for o in sim_objects],
MakeObjectsInitFile)
PySource('m5.objects', 'python/m5/objects/__init__.py')
swig_modules = []
for source in swig_sources:
source.rfile() # Hack to cause the symlink to the .i file to be created
package = swig_source_packages[source]
filename = str(source)
module = basename(filename)
assert(module.endswith('.i'))
module = module[:-2]
cc_file = 'swig/%s_wrap.cc' % module
py_file = 'm5/internal/%s.py' % module
env.Command([cc_file, py_file], source,
'$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
'-o ${TARGETS[0]} $SOURCES')
env.Depends(py_file, source)
env.Depends(cc_file, source)
swig_modules.append(Value(module))
Source(cc_file)
PySource(package, py_file)
def MakeSwigInit(target, source, env):
f = file(str(target[0]), 'w')
print >>f, 'extern "C" {'
for module in source:
print >>f, ' void init_%s();' % module.get_contents()
print >>f, '}'
print >>f, 'void init_swig() {'
for module in source:
print >>f, ' init_%s();' % module.get_contents()
print >>f, '}'
f.close()
env.Command('python/swig/init.cc', swig_modules, MakeSwigInit)
def CompilePyFile(target, source, env):
import py_compile
py_compile.compile(str(source[0]), str(target[0]))
py_compiled = []
py_arcname = {}
py_zip_depends = []
for source in py_sources:
filename = str(source)
package = py_source_packages[source]
arc_path = package.split('.') + [ basename(filename) + 'c' ]
zip_path = [ 'zip' ] + arc_path
arcname = joinpath(*arc_path)
zipname = joinpath(*zip_path)
f = File(zipname)
env.Command(f, source, CompilePyFile)
py_compiled.append(f)
py_arcname[f] = arcname
# make the zipfile depend on the archive name so that the archive
# is rebuilt if the name changes
py_zip_depends.append(Value(arcname))
# Action function to build the zip archive. Uses the PyZipFile module
# included in the standard Python library.
def buildPyZip(target, source, env):
zf = zipfile.ZipFile(str(target[0]), 'w')
for s in source:
arcname = py_arcname[s]
zipname = str(s)
zf.write(zipname, arcname)
zf.close()
# Add the zip file target to the environment.
env.Command('m5py.zip', py_compiled, buildPyZip)
env.Depends('m5py.zip', py_zip_depends)
########################################################################
#
# Define binaries. Each different build type (debug, opt, etc.) gets
# a slightly different build environment.
#
# List of constructed environments to pass back to SConstruct
envList = []
# This function adds the specified sources to the given build
# environment, and returns a list of all the corresponding SCons
# Object nodes (including an extra one for date.cc). We explicitly
@ -92,16 +263,6 @@ def make_objs(sources, env):
objs.append(date_obj)
return objs
###################################################
#
# Define binaries. Each different build type (debug, opt, etc.) gets
# a slightly different build environment.
#
###################################################
# List of constructed environments to pass back to SConstruct
envList = []
# Function to create a new build environment as clone of current
# environment 'env' with modified object suffix and optional stripped
# binary. Additional keyword arguments are appended to corresponding
@ -120,7 +281,7 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
else:
newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET')
bin = stripped_bin
targets = newEnv.Concat(exe, [bin, 'python/m5py.zip'])
targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
newEnv.M5Binary = targets[0]
envList.append(newEnv)

View file

@ -245,13 +245,13 @@ AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc)
{
AlphaISA::PTE &pte = tc->getDTBPtr()->index(!tc->misspeculating());
retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
retval |= ((uint64_t)pte.ppn & ULL(0x7ffffff)) << 32;
retval |= ((uint64_t)pte.xre & ULL(0xf)) << 8;
retval |= ((uint64_t)pte.xwe & ULL(0xf)) << 12;
retval |= ((uint64_t)pte.fonr & ULL(0x1)) << 1;
retval |= ((uint64_t)pte.fonw & ULL(0x1))<< 2;
retval |= ((uint64_t)pte.asma & ULL(0x1)) << 4;
retval |= ((uint64_t)pte.asn & ULL(0x7f)) << 57;
}
break;

View file

@ -35,7 +35,7 @@
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/types.hh"
#include <string.h>
#include <cstring>
#include <iostream>
class Checkpoint;
@ -61,7 +61,7 @@ namespace AlphaISA
void unserialize(Checkpoint *cp, const std::string &section);
void clear()
{ bzero(d, sizeof(d)); }
{ std::memset(d, 0, sizeof(d)); }
};
}

View file

@ -35,7 +35,7 @@
#include "arch/alpha/types.hh"
#include <iostream>
#include <strings.h>
#include <cstring>
class Checkpoint;
@ -71,7 +71,7 @@ namespace AlphaISA
void unserialize(Checkpoint *cp, const std::string &section);
void clear()
{ bzero(regs, sizeof(regs)); }
{ std::memset(regs, 0, sizeof(regs)); }
};
}

View file

@ -192,10 +192,10 @@ output decoder {{
}
const int AlphaFP::alphaToC99RoundingMode[] = {
FE_TOWARDZERO, // Chopped
FE_DOWNWARD, // Minus_Infinity
FE_TONEAREST, // Normal
FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
M5_FE_TOWARDZERO, // Chopped
M5_FE_DOWNWARD, // Minus_Infinity
M5_FE_TONEAREST, // Normal
M5_FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
};
const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
@ -228,10 +228,10 @@ def template FloatingPointExecute {{
if (roundingMode == Normal) {
%(code)s;
} else {
fesetround(getC99RoundingMode(
m5_fesetround(getC99RoundingMode(
xc->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR)));
%(code)s;
fesetround(FE_TONEAREST);
m5_fesetround(M5_FE_TONEAREST);
}
#else
if (roundingMode != Normal && !warnedOnRounding) {

View file

@ -213,7 +213,7 @@ TLB::flushAddr(Addr addr, uint8_t asn)
if (i == lookupTable.end())
return;
while (i->first == vaddr.vpn()) {
while (i != lookupTable.end() && i->first == vaddr.vpn()) {
int index = i->second;
PTE *pte = &table[index];
assert(pte->valid);
@ -225,10 +225,10 @@ TLB::flushAddr(Addr addr, uint8_t asn)
// invalidate this entry
pte->valid = false;
lookupTable.erase(i);
lookupTable.erase(i++);
} else {
++i;
}
++i;
}
}

View file

@ -154,6 +154,76 @@ def template ROrImmDecode {{
}
}};
output header {{
union DoubleSingle
{
double d;
uint64_t ui;
uint32_t s[2];
DoubleSingle(double _d) : d(_d)
{}
DoubleSingle(uint64_t _ui) : ui(_ui)
{}
DoubleSingle(uint32_t _s0, uint32_t _s1)
{
s[0] = _s0;
s[1] = _s1;
}
};
}};
let {{
def filterDoubles(code):
assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
for opName in ("Frd", "Frs1", "Frs2", "Frd_N"):
next_pos = 0
operandsREString = (r'''
(?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
(?![\w\.]) # neg. lookahead assertion: prevent partial matches
''' % opName)
operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
is_src = False
is_dest = False
extension = None
foundOne = False
while 1:
match = operandsRE.search(code, next_pos)
if not match:
break
foundOne = True
op = match.groups()
(op_full, op_base, op_ext) = op
is_dest_local = (assignRE.match(code, match.end()) != None)
is_dest = is_dest or is_dest_local
is_src = is_src or not is_dest_local
if extension and extension != op_ext:
raise Exception, "Inconsistent extensions in double filter."
extension = op_ext
next_pos = match.end()
if foundOne:
# Get rid of any unwanted extension
code = operandsRE.sub(op_base, code)
is_int = False
member = "d"
if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"):
is_int = True
member = "ui"
if is_src:
code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \
(opName, opName, opName, member)) + code
if is_dest:
code += '''
%s_low = DoubleSingle(%s).s[1];
%s_high = DoubleSingle(%s).s[0];''' % \
(opName, opName, opName, opName)
if is_int:
code = ("uint64_t %s;" % opName) + code
else:
code = ("double %s;" % opName) + code
return code
}};
let {{
def splitOutImm(code):
matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')

View file

@ -97,6 +97,7 @@ def template BasicDecodeWithMnemonic {{
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
code = filterDoubles(code)
iop = InstObjParams(name, Name, 'SparcStaticInst', code, flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
@ -108,38 +109,24 @@ def format FpBasic(code, *flags) {{
fp_code = """
Fsr |= bits(Fsr,4,0) << 5;
Fsr = insertBits(Fsr,4,0,0);
#if defined(__sun) || defined (__OpenBSD__)
fp_rnd newrnd = FP_RN;
int newrnd = M5_FE_TONEAREST;
switch (Fsr<31:30>) {
case 0: newrnd = FP_RN; break;
case 1: newrnd = FP_RZ; break;
case 2: newrnd = FP_RP; break;
case 3: newrnd = FP_RM; break;
case 0: newrnd = M5_FE_TONEAREST; break;
case 1: newrnd = M5_FE_TOWARDZERO; break;
case 2: newrnd = M5_FE_UPWARD; break;
case 3: newrnd = M5_FE_DOWNWARD; break;
}
fp_rnd oldrnd = fpsetround(newrnd);
#else
int newrnd = FE_TONEAREST;
switch (Fsr<31:30>) {
case 0: newrnd = FE_TONEAREST; break;
case 1: newrnd = FE_TOWARDZERO; break;
case 2: newrnd = FE_UPWARD; break;
case 3: newrnd = FE_DOWNWARD; break;
}
int oldrnd = fegetround();
fesetround(newrnd);
#endif
int oldrnd = m5_fegetround();
m5_fesetround(newrnd);
"""
fp_code += code
fp_code += """
#if defined(__sun) || defined (__OpenBSD__)
fpsetround(oldrnd);
#else
fesetround(oldrnd);
#endif
m5_fesetround(oldrnd);
"""
fp_code = filterDoubles(fp_code)
iop = InstObjParams(name, Name, 'SparcStaticInst', fp_code, flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)

View file

@ -71,6 +71,7 @@ let {{
}};
def format LoadAlt(code, asi, *opt_flags) {{
code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,
@ -79,6 +80,7 @@ def format LoadAlt(code, asi, *opt_flags) {{
}};
def format StoreAlt(code, asi, *opt_flags) {{
code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,
@ -87,6 +89,7 @@ def format StoreAlt(code, asi, *opt_flags) {{
}};
def format Load(code, *opt_flags) {{
code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,
@ -95,6 +98,7 @@ def format Load(code, *opt_flags) {{
}};
def format Store(code, *opt_flags) {{
code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,

View file

@ -317,6 +317,7 @@ let {{
}};
def format BlockLoad(code, asi, *opt_flags) {{
code = filterDoubles(code)
# We need to make sure to check the highest priority fault last.
# That way, if other faults have been detected, they'll be overwritten
# rather than the other way around.
@ -329,6 +330,7 @@ def format BlockLoad(code, asi, *opt_flags) {{
}};
def format BlockStore(code, asi, *opt_flags) {{
code = filterDoubles(code)
# We need to make sure to check the highest priority fault last.
# That way, if other faults have been detected, they'll be overwritten
# rather than the other way around.

View file

@ -39,7 +39,7 @@ def template SwapExecute {{
Addr EA;
%(fp_enable_check)s;
%(op_decl)s;
uint64_t mem_data;
uint64_t mem_data = 0;
%(op_rd)s;
%(ea_code)s;

View file

@ -1,4 +1,4 @@
// Copyright (c) 2006 The Regents of The University of Michigan
// Copyright (c) 2006-2007 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -26,6 +26,33 @@
//
// Authors: Gabe Black
//This delcares the initiateAcc function in memory operations
def template MacroInitiateAcc {{
Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const
{
panic("Tried to execute a macroop directly!\n");
return NoFault;
}
}};
def template MacroCompleteAcc {{
Fault completeAcc(PacketPtr, %(CPU_exec_context)s *,
Trace::InstRecord *) const
{
panic("Tried to execute a macroop directly!\n");
return NoFault;
}
}};
//This template provides the execute functions for a store
def template MacroExecute {{
Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
{
panic("Tried to execute a macroop directly!\n");
return NoFault;
}
}};
output header {{
class SparcMacroInst : public SparcStaticInst
@ -60,7 +87,9 @@ output header {{
return microOps[microPC];
}
%(BasicExecPanic)s
%(MacroExecute)s
%(MacroInitiateAcc)s
%(MacroCompleteAcc)s
};
class SparcMicroInst : public SparcStaticInst

View file

@ -53,22 +53,14 @@ output decoder {{
#include "cpu/thread_context.hh" // for Jump::branchTarget()
#include "mem/packet.hh"
#if defined(linux) || defined(__APPLE__)
#include <fenv.h>
#endif
#include "base/fenv.hh"
#include <algorithm>
using namespace SparcISA;
}};
output exec {{
#if defined(linux) || defined(__APPLE__)
#include <fenv.h>
#endif
#if defined(__sun) || defined (__OpenBSD__)
#include <ieeefp.h>
#endif
#include "base/fenv.hh"
#if FULL_SYSTEM
#include "sim/pseudo_inst.hh"

View file

@ -52,6 +52,16 @@ output header {{
{
return (regNum & (~1)) | ((regNum & 1) << 5);
}
static inline unsigned int dfprl(unsigned int regNum)
{
return dfpr(regNum) & (~0x1);
}
static inline unsigned int dfprh(unsigned int regNum)
{
return dfpr(regNum) | 0x1;
}
}};
def operands {{
@ -79,21 +89,43 @@ def operands {{
# differently, they get different operands. The single precision versions
# have an s post pended to their name.
'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10),
'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
#'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
'Frd_low': ('FloatReg', 'uw', 'dfprl(RD)', 'IsFloating', 10),
'Frd_high': ('FloatReg', 'uw', 'dfprh(RD)', 'IsFloating', 10),
# Each Frd_N refers to the Nth double precision register from Frd.
# Note that this adds twice N to the register number.
'Frd_0': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
'Frd_1': ('FloatReg', 'df', 'dfpr(RD) + 2', 'IsFloating', 10),
'Frd_2': ('FloatReg', 'df', 'dfpr(RD) + 4', 'IsFloating', 10),
'Frd_3': ('FloatReg', 'df', 'dfpr(RD) + 6', 'IsFloating', 10),
'Frd_4': ('FloatReg', 'df', 'dfpr(RD) + 8', 'IsFloating', 10),
'Frd_5': ('FloatReg', 'df', 'dfpr(RD) + 10', 'IsFloating', 10),
'Frd_6': ('FloatReg', 'df', 'dfpr(RD) + 12', 'IsFloating', 10),
'Frd_7': ('FloatReg', 'df', 'dfpr(RD) + 14', 'IsFloating', 10),
#'Frd_0': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
'Frd_0_low': ('FloatReg', 'uw', 'dfprl(RD)', 'IsFloating', 10),
'Frd_0_high': ('FloatReg', 'uw', 'dfprh(RD)', 'IsFloating', 10),
#'Frd_1': ('FloatReg', 'df', 'dfpr(RD) + 2', 'IsFloating', 10),
'Frd_1_low': ('FloatReg', 'uw', 'dfprl(RD) + 2', 'IsFloating', 10),
'Frd_1_high': ('FloatReg', 'uw', 'dfprh(RD) + 2', 'IsFloating', 10),
#'Frd_2': ('FloatReg', 'df', 'dfpr(RD) + 4', 'IsFloating', 10),
'Frd_2_low': ('FloatReg', 'uw', 'dfprl(RD) + 4', 'IsFloating', 10),
'Frd_2_high': ('FloatReg', 'uw', 'dfprh(RD) + 4', 'IsFloating', 10),
#'Frd_3': ('FloatReg', 'df', 'dfpr(RD) + 6', 'IsFloating', 10),
'Frd_3_low': ('FloatReg', 'uw', 'dfprl(RD) + 6', 'IsFloating', 10),
'Frd_3_high': ('FloatReg', 'uw', 'dfprh(RD) + 6', 'IsFloating', 10),
#'Frd_4': ('FloatReg', 'df', 'dfpr(RD) + 8', 'IsFloating', 10),
'Frd_4_low': ('FloatReg', 'uw', 'dfprl(RD) + 8', 'IsFloating', 10),
'Frd_4_high': ('FloatReg', 'uw', 'dfprh(RD) + 8', 'IsFloating', 10),
#'Frd_5': ('FloatReg', 'df', 'dfpr(RD) + 10', 'IsFloating', 10),
'Frd_5_low': ('FloatReg', 'uw', 'dfprl(RD) + 10', 'IsFloating', 10),
'Frd_5_high': ('FloatReg', 'uw', 'dfprh(RD) + 10', 'IsFloating', 10),
#'Frd_6': ('FloatReg', 'df', 'dfpr(RD) + 12', 'IsFloating', 10),
'Frd_6_low': ('FloatReg', 'uw', 'dfprl(RD) + 12', 'IsFloating', 10),
'Frd_6_high': ('FloatReg', 'uw', 'dfprh(RD) + 12', 'IsFloating', 10),
#'Frd_7': ('FloatReg', 'df', 'dfpr(RD) + 14', 'IsFloating', 10),
'Frd_7_low': ('FloatReg', 'uw', 'dfprl(RD) + 14', 'IsFloating', 10),
'Frd_7_high': ('FloatReg', 'uw', 'dfprh(RD) + 14', 'IsFloating', 10),
'Frs1s': ('FloatReg', 'sf', 'RS1', 'IsFloating', 11),
'Frs1': ('FloatReg', 'df', 'dfpr(RS1)', 'IsFloating', 11),
#'Frs1': ('FloatReg', 'df', 'dfpr(RS1)', 'IsFloating', 11),
'Frs1_low': ('FloatReg', 'uw', 'dfprl(RS1)', 'IsFloating', 11),
'Frs1_high': ('FloatReg', 'uw', 'dfprh(RS1)', 'IsFloating', 11),
'Frs2s': ('FloatReg', 'sf', 'RS2', 'IsFloating', 12),
'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
#'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
'Frs2_low': ('FloatReg', 'uw', 'dfprl(RS2)', 'IsFloating', 12),
'Frs2_high': ('FloatReg', 'uw', 'dfprh(RS2)', 'IsFloating', 12),
'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
# Registers which are used explicitly in instructions

View file

@ -39,6 +39,7 @@
#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/process_impl.hh"
#include "mem/translating_port.hh"
#include "sim/system.hh"

View file

@ -95,6 +95,7 @@
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "mem/translating_port.hh"
#include "sim/process_impl.hh"
#include "sim/system.hh"
using namespace std;

View file

@ -57,6 +57,7 @@ Source('circlebuf.cc')
Source('cprintf.cc')
Source('crc.cc')
Source('fast_alloc.cc')
Source('fenv.c')
Source('fifo_buffer.cc')
Source('hostinfo.cc')
Source('hybrid_pred.cc')
@ -97,3 +98,5 @@ Source('stats/visit.cc')
if env['USE_MYSQL']:
Source('mysql.cc')
Source('stats/mysql.cc')
PySource('m5', 'traceflags.py')

View file

@ -96,8 +96,9 @@ inline
T
insertBits(T val, int first, int last, B bit_val)
{
T t_bit_val = bit_val;
T bmask = mask(first - last + 1) << last;
return ((bit_val << last) & bmask) | (val & ~bmask);
return ((t_bit_val << last) & bmask) | (val & ~bmask);
}
/**

56
src/base/fenv.c Normal file
View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2007 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: Ali Saidi
*/
#include <assert.h>
#include <stdlib.h>
#include <fenv.h>
void m5_fesetround(int rm);
int m5_fegetround();
static const int m5_round_ops[] = {FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD};
void m5_fesetround(int rm)
{
assert(rm > 0 && rm < 4);
fesetround(m5_round_ops[rm]);
}
int m5_fegetround()
{
int x;
int rm = fegetround();
for(x = 0; x < 4; x++)
if (m5_round_ops[x] == rm)
return x;
abort();
return 0;
}

View file

@ -33,20 +33,21 @@
#include "config/use_fenv.hh"
#define M5_FE_DOWNWARD 0
#define M5_FE_TONEAREST 1
#define M5_FE_TOWARDZERO 2
#define M5_FE_UPWARD 3
#if USE_FENV
#include <fenv.h>
extern "C" {
void m5_fesetround(int rm);
int m5_fegetround();
}
#else
// Dummy definitions to allow code to compile w/o a real <fenv.h>.
#define FE_TONEAREST 0
#define FE_DOWNWARD 0
#define FE_UPWARD 0
#define FE_TOWARDZERO 0
inline int fesetround(int rounding_mode) { return 0; }
inline void m5_fesetround(int rm) { ; }
inline int m5_fegetround() {return 0; }
#endif // USE_FENV

View file

@ -29,9 +29,6 @@
* Ali Saidi
*/
#if defined(__sun)
#include <ieeefp.h>
#endif
#ifdef __SUNPRO_CC
#include <stdlib.h>
#include <math.h>
@ -40,6 +37,7 @@
#include <cstdlib>
#include <cmath>
#include "base/fenv.hh"
#include "base/random.hh"
using namespace std;
@ -61,9 +59,10 @@ m5round(double r)
{
#if defined(__sun)
double val;
fp_rnd oldrnd = fpsetround(FP_RN);
int oldrnd = m5_fegetround();
m5_fesetround(M5_FE_TONEAREST);
val = rint(r);
fpsetround(oldrnd);
m5_fesetround(oldrnd);
return val;
#else
return round(r);

View file

@ -2094,9 +2094,13 @@ class UnaryNode : public Node
return vresult;
}
Result total() const {
Op op;
return op(l->total());
Result total() const
{
const VResult &vec = this->result();
Result total = 0;
for (int i = 0; i < size(); i++)
total += vec[i];
return total;
}
virtual size_t size() const { return l->size(); }
@ -2149,9 +2153,13 @@ class BinaryNode : public Node
return vresult;
}
Result total() const {
Op op;
return op(l->total(), r->total());
Result total() const
{
const VResult &vec = this->result();
Result total = 0;
for (int i = 0; i < size(); i++)
total += vec[i];
return total;
}
virtual size_t size() const {

View file

@ -641,9 +641,6 @@ DefaultCommit<Impl>::handleInterrupt()
// an interrupt needed to be handled.
DPRINTF(Commit, "Interrupt detected.\n");
Fault new_interrupt = cpu->getInterrupts();
assert(new_interrupt != NoFault);
// Clear the interrupt now that it's going to be handled
toIEW->commitInfo[0].clearInterrupt = true;

View file

@ -384,25 +384,25 @@ FullO3CPU<Impl>::fullCPURegStats()
.name(name() + ".cpi")
.desc("CPI: Cycles Per Instruction")
.precision(6);
cpi = simTicks / committedInsts;
cpi = numCycles / committedInsts;
totalCpi
.name(name() + ".cpi_total")
.desc("CPI: Total CPI of All Threads")
.precision(6);
totalCpi = simTicks / totalCommittedInsts;
totalCpi = numCycles / totalCommittedInsts;
ipc
.name(name() + ".ipc")
.desc("IPC: Instructions Per Cycle")
.precision(6);
ipc = committedInsts / simTicks;
ipc = committedInsts / numCycles;
totalIpc
.name(name() + ".ipc_total")
.desc("IPC: Total IPC of All Threads")
.precision(6);
totalIpc = totalCommittedInsts / simTicks;
totalIpc = totalCommittedInsts / numCycles;
}

View file

@ -33,6 +33,7 @@
#define __CPU_O3_LSQ_UNIT_HH__
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
@ -292,7 +293,7 @@ class LSQUnit {
: inst(NULL), req(NULL), size(0),
canWB(0), committed(0), completed(0)
{
bzero(data, sizeof(data));
std::memset(data, 0, sizeof(data));
}
/** Constructs a store queue entry for a given instruction. */
@ -300,7 +301,7 @@ class LSQUnit {
: inst(_inst), req(NULL), size(0),
canWB(0), committed(0), completed(0)
{
bzero(data, sizeof(data));
std::memset(data, 0, sizeof(data));
}
/** The store instruction. */

View file

@ -680,7 +680,6 @@ LSQUnit<Impl>::writebackStores()
inst->seqNum);
WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
wb->schedule(curTick + 1);
delete state;
completeStore(storeWBIdx);
incrStIdx(storeWBIdx);
continue;

View file

@ -79,7 +79,7 @@ BaseSimpleCPU::BaseSimpleCPU(Params *p)
/* asid */ 0);
#endif // !FULL_SYSTEM
thread->setStatus(ThreadContext::Suspended);
thread->setStatus(ThreadContext::Unallocated);
tc = thread->getTC();

View file

@ -574,10 +574,16 @@ TimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt)
return true;
}
else {
//Snooping a Coherence Request, do nothing
return true;
else if (pkt->result == Packet::Nacked) {
assert(cpu->_status == IcacheWaitResponse);
pkt->reinitNacked();
if (!sendTiming(pkt)) {
cpu->_status = IcacheRetry;
cpu->ifetch_pkt = pkt;
}
}
//Snooping a Coherence Request, do nothing
return true;
}
void
@ -663,10 +669,16 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt)
return true;
}
else {
//Snooping a coherence req, do nothing
return true;
else if (pkt->result == Packet::Nacked) {
assert(cpu->_status == DcacheWaitResponse);
pkt->reinitNacked();
if (!sendTiming(pkt)) {
cpu->_status = DcacheRetry;
cpu->dcache_pkt = pkt;
}
}
//Snooping a Coherence Request, do nothing
return true;
}
void

View file

@ -221,10 +221,10 @@ SimpleThread::activate(int delay)
lastActivate = curTick;
if (status() == ThreadContext::Unallocated) {
cpu->activateWhenReady(tid);
return;
}
// if (status() == ThreadContext::Unallocated) {
// cpu->activateWhenReady(tid);
// return;
// }
_status = ThreadContext::Active;

View file

@ -169,9 +169,8 @@ ThreadState::getMemPort()
return port;
/* Use this port to for syscall emulation writes to memory. */
port = new TranslatingPort(csprintf("%s-%d-funcport",
baseCpu->name(), tid),
process->pTable, false);
port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), tid),
process, TranslatingPort::NextPage);
connectToMemFunc(port);

View file

@ -76,7 +76,7 @@ AlphaConsole::AlphaConsole(Params *p)
alphaAccess->diskOperation = 0;
alphaAccess->outputChar = 0;
alphaAccess->inputChar = 0;
bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
std::memset(alphaAccess->cpuStack, 0, sizeof(alphaAccess->cpuStack));
}

View file

@ -63,6 +63,9 @@ class EtherInt : public SimObject
bool sendPacket(EthPacketPtr packet)
{ return peer ? peer->recvPacket(packet) : true; }
virtual bool recvPacket(EthPacketPtr packet) = 0;
bool askBusy() {return peer->isBusy(); }
virtual bool isBusy() { return false; }
};
#endif // __DEV_ETHERINT_HH__

View file

@ -114,6 +114,7 @@ class EtherLink : public SimObject
Interface(const std::string &name, Link *txlink, Link *rxlink);
bool recvPacket(EthPacketPtr packet) { return txlink->transmit(packet); }
void sendDone() { peer->sendDone(); }
bool isBusy() { return txlink->busy(); }
};
Link *link[2];

View file

@ -656,7 +656,7 @@ IGbE::RxDescCache::writePacket(EthPacketPtr packet)
return false;
pktPtr = packet;
pktDone = false;
igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf),
packet->length, &pktEvent, packet->data);
return true;
@ -683,8 +683,12 @@ IGbE::RxDescCache::pktComplete()
uint8_t status = RXDS_DD | RXDS_EOP;
uint8_t err = 0;
IpPtr ip(pktPtr);
if (ip) {
DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n", ip->id());
if (igbe->regs.rxcsum.ipofld()) {
DPRINTF(EthernetDesc, "Checking IP checksum\n");
status |= RXDS_IPCS;
@ -710,12 +714,15 @@ IGbE::RxDescCache::pktComplete()
DPRINTF(EthernetDesc, "Checking UDP checksum\n");
status |= RXDS_UDPCS;
desc->csum = htole(cksum(udp));
if (cksum(tcp) != 0) {
if (cksum(udp) != 0) {
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
err |= RXDE_TCPE;
}
}
} // if ip
} else { // if ip
DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n");
}
desc->status = htole(status);
desc->errors = htole(err);
@ -727,12 +734,8 @@ IGbE::RxDescCache::pktComplete()
if (igbe->regs.rdtr.delay()) {
DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n",
igbe->regs.rdtr.delay() * igbe->intClock());
if (igbe->rdtrEvent.scheduled())
igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() *
igbe->intClock());
else
igbe->rdtrEvent.schedule(curTick + igbe->regs.rdtr.delay() *
igbe->intClock());
igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() *
igbe->intClock(),true);
}
if (igbe->regs.radv.idv() && igbe->regs.rdtr.delay()) {
@ -895,6 +898,7 @@ IGbE::TxDescCache::pktComplete()
pktPtr = NULL;
DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n");
enableSm();
return;
}
@ -915,10 +919,20 @@ IGbE::TxDescCache::pktComplete()
DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
if (DTRACE(EthernetDesc)) {
IpPtr ip(pktPtr);
if (ip)
DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n",
ip->id());
else
DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n");
}
// Checksums are only ofloaded for new descriptor types
if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) {
DPRINTF(EthernetDesc, "Calculating checksums for packet\n");
IpPtr ip(pktPtr);
if (TxdOp::ixsm(desc)) {
ip->sum(0);
ip->sum(cksum(ip));
@ -927,11 +941,13 @@ IGbE::TxDescCache::pktComplete()
if (TxdOp::txsm(desc)) {
if (isTcp) {
TcpPtr tcp(ip);
assert(tcp);
tcp->sum(0);
tcp->sum(cksum(tcp));
DPRINTF(EthernetDesc, "Calculated TCP checksum\n");
} else {
UdpPtr udp(ip);
assert(udp);
udp->sum(0);
udp->sum(cksum(udp));
DPRINTF(EthernetDesc, "Calculated UDP checksum\n");
@ -944,12 +960,8 @@ IGbE::TxDescCache::pktComplete()
DPRINTF(EthernetDesc, "Descriptor had IDE set\n");
if (igbe->regs.tidv.idv()) {
DPRINTF(EthernetDesc, "setting tidv\n");
if (igbe->tidvEvent.scheduled())
igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
igbe->intClock());
else
igbe->tidvEvent.schedule(curTick + igbe->regs.tidv.idv() *
igbe->intClock());
igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
igbe->intClock(), true);
}
if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {
@ -977,6 +989,7 @@ IGbE::TxDescCache::pktComplete()
DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
writeback((igbe->cacheBlockSize()-1)>>4);
}
enableSm();
igbe->checkDrain();
}
@ -1028,7 +1041,7 @@ IGbE::TxDescCache::hasOutstandingEvents()
void
IGbE::restartClock()
{
if (!tickEvent.scheduled() && (rxTick || txTick) && getState() ==
if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) && getState() ==
SimObject::Running)
tickEvent.schedule((curTick/cycles(1)) * cycles(1) + cycles(1));
}
@ -1156,6 +1169,8 @@ IGbE::txStateMachine()
return;
}
DPRINTF(EthernetSM, "TXS: Nothing to do, stopping ticking\n");
txTick = false;
}
bool
@ -1194,6 +1209,7 @@ IGbE::rxStateMachine()
// If the packet is done check for interrupts/descriptors/etc
if (rxDescCache.packetDone()) {
rxDmaPacket = false;
DPRINTF(EthernetSM, "RXS: Packet completed DMA to memory\n");
int descLeft = rxDescCache.descLeft();
switch (regs.rctl.rdmts()) {
@ -1238,6 +1254,12 @@ IGbE::rxStateMachine()
return;
}
if (rxDmaPacket) {
DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");
rxTick = false;
return;
}
if (!rxDescCache.descUnused()) {
DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n");
rxTick = false;
@ -1264,6 +1286,7 @@ IGbE::rxStateMachine()
rxFifo.pop();
DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");
rxTick = false;
rxDmaPacket = true;
}
void
@ -1458,6 +1481,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
Param<Tick> min_backoff_delay;
Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@ -1479,6 +1504,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@ -1503,6 +1530,8 @@ CREATE_SIM_OBJECT(IGbE)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
params->min_backoff_delay = min_backoff_delay;
params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;

View file

@ -80,6 +80,8 @@ class IGbE : public PciDev
bool txTick;
bool txFifoTick;
bool rxDmaPacket;
// Event and function to deal with RDTR timer expiring
void rdtrProcess() {
rxDescCache.writeback(0);

View file

@ -751,6 +751,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
Param<Tick> min_backoff_delay;
Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@ -765,6 +767,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@ -781,6 +785,8 @@ CREATE_SIM_OBJECT(IdeController)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
params->min_backoff_delay = min_backoff_delay;
params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;

View file

@ -93,7 +93,8 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
DmaPort::DmaPort(DmaDevice *dev, System *s)
: Port(dev->name() + "-dmaport", dev), device(dev), sys(s),
pendingCount(0), actionInProgress(0), drainEvent(NULL)
pendingCount(0), actionInProgress(0), drainEvent(NULL),
backoffTime(0), inRetry(false), backoffEvent(this)
{ }
bool
@ -104,12 +105,24 @@ DmaPort::recvTiming(PacketPtr pkt)
if (pkt->result == Packet::Nacked) {
DPRINTF(DMA, "Received nacked Pkt %#x with State: %#x Addr: %#x\n",
pkt, pkt->senderState, pkt->getAddr());
if (backoffTime < device->minBackoffDelay)
backoffTime = device->minBackoffDelay;
else if (backoffTime < device->maxBackoffDelay)
backoffTime <<= 1;
backoffEvent.reschedule(curTick + backoffTime, true);
DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime);
pkt->reinitNacked();
sendDma(pkt, true);
queueDma(pkt, true);
} else if (pkt->senderState) {
DmaReqState *state;
DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x\n",
pkt, pkt->senderState, pkt->getAddr());
backoffTime >>= 2;
DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x size: %#x\n",
pkt, pkt->senderState, pkt->getAddr(), pkt->req->getSize());
state = dynamic_cast<DmaReqState*>(pkt->senderState);
pendingCount--;
@ -117,6 +130,7 @@ DmaPort::recvTiming(PacketPtr pkt)
assert(state);
state->numBytes += pkt->req->getSize();
assert(state->totBytes >= state->numBytes);
if (state->totBytes == state->numBytes) {
state->completionEvent->process();
delete state;
@ -136,7 +150,8 @@ DmaPort::recvTiming(PacketPtr pkt)
}
DmaDevice::DmaDevice(Params *p)
: PioDevice(p), dmaPort(NULL)
: PioDevice(p), dmaPort(NULL), minBackoffDelay(p->min_backoff_delay),
maxBackoffDelay(p->max_backoff_delay)
{ }
@ -165,19 +180,31 @@ DmaPort::drain(Event *de)
void
DmaPort::recvRetry()
{
assert(transmitList.size());
PacketPtr pkt = transmitList.front();
bool result = true;
while (result && transmitList.size()) {
do {
DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n",
pkt, pkt->senderState);
result = sendTiming(pkt);
if (result) {
DPRINTF(DMA, "-- Done\n");
transmitList.pop_front();
inRetry = false;
} else {
inRetry = true;
DPRINTF(DMA, "-- Failed, queued\n");
}
} while (!backoffTime && result && transmitList.size());
if (transmitList.size() && backoffTime && !inRetry) {
DPRINTF(DMA, "Scheduling backoff for %d\n", curTick+backoffTime);
if (!backoffEvent.scheduled())
backoffEvent.schedule(backoffTime+curTick);
}
DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n",
transmitList.size(), backoffTime, inRetry,
backoffEvent.scheduled());
}
@ -191,6 +218,9 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
DmaReqState *reqState = new DmaReqState(event, this, size);
DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size,
event->scheduled());
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
Request *req = new Request(gen.addr(), gen.size(), 0);
@ -204,41 +234,80 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
assert(pendingCount >= 0);
pendingCount++;
sendDma(pkt);
DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
gen.size());
queueDma(pkt);
}
}
void
DmaPort::queueDma(PacketPtr pkt, bool front)
{
if (front)
transmitList.push_front(pkt);
else
transmitList.push_back(pkt);
sendDma();
}
void
DmaPort::sendDma(PacketPtr pkt, bool front)
DmaPort::sendDma()
{
// some kind of selction between access methods
// more work is going to have to be done to make
// switching actually work
assert(transmitList.size());
PacketPtr pkt = transmitList.front();
System::MemoryMode state = sys->getMemoryMode();
if (state == System::Timing) {
if (backoffEvent.scheduled() || inRetry) {
DPRINTF(DMA, "Can't send immediately, waiting for retry or backoff timer\n");
return;
}
DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
pkt, pkt->getAddr());
if (transmitList.size() || !sendTiming(pkt)) {
if (front)
transmitList.push_front(pkt);
else
transmitList.push_back(pkt);
DPRINTF(DMA, "-- Failed: queued\n");
} else {
DPRINTF(DMA, "-- Done\n");
bool result;
do {
result = sendTiming(pkt);
if (result) {
transmitList.pop_front();
DPRINTF(DMA, "-- Done\n");
} else {
inRetry = true;
DPRINTF(DMA, "-- Failed: queued\n");
}
} while (result && !backoffTime && transmitList.size());
if (transmitList.size() && backoffTime && !inRetry &&
!backoffEvent.scheduled()) {
DPRINTF(DMA, "-- Scheduling backoff timer for %d\n",
backoffTime+curTick);
backoffEvent.schedule(backoffTime+curTick);
}
} else if (state == System::Atomic) {
transmitList.pop_front();
Tick lat;
DPRINTF(DMA, "--Sending DMA for addr: %#x size: %d\n",
pkt->req->getPaddr(), pkt->req->getSize());
lat = sendAtomic(pkt);
assert(pkt->senderState);
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
assert(state);
state->numBytes += pkt->req->getSize();
DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n",
pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes,
state->totBytes, state->completionEvent->scheduled());
if (state->totBytes == state->numBytes) {
assert(!state->completionEvent->scheduled());
state->completionEvent->schedule(curTick + lat);
delete state;
delete pkt->req;

View file

@ -107,6 +107,14 @@ class DmaPort : public Port
* here.*/
Event *drainEvent;
/** time to wait between sending another packet, increases as NACKs are
* recived, decreases as responses are recived. */
Tick backoffTime;
/** If the port is currently waiting for a retry before it can send whatever
* it is that it's sending. */
bool inRetry;
virtual bool recvTiming(PacketPtr pkt);
virtual Tick recvAtomic(PacketPtr pkt)
{ panic("dma port shouldn't be used for pio access."); M5_DUMMY_RETURN }
@ -122,7 +130,11 @@ class DmaPort : public Port
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
void sendDma(PacketPtr pkt, bool front = false);
void queueDma(PacketPtr pkt, bool front = false);
void sendDma();
/** event to give us a kick every time we backoff time is reached. */
EventWrapper<DmaPort, &DmaPort::sendDma> backoffEvent;
public:
DmaPort(DmaDevice *dev, System *s);
@ -249,8 +261,17 @@ class BasicPioDevice : public PioDevice
class DmaDevice : public PioDevice
{
protected:
public:
struct Params : public PioDevice::Params
{
Tick min_backoff_delay;
Tick max_backoff_delay;
};
protected:
DmaPort *dmaPort;
Tick minBackoffDelay;
Tick maxBackoffDelay;
public:
DmaDevice(Params *p);

View file

@ -2310,10 +2310,7 @@ NSGigE::transferDone()
DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
if (txEvent.scheduled())
txEvent.reschedule(curTick + cycles(1));
else
txEvent.schedule(curTick + cycles(1));
txEvent.reschedule(curTick + cycles(1), true);
}
bool
@ -2812,6 +2809,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
Param<Tick> min_backoff_delay;
Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@ -2846,6 +2845,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@ -2884,6 +2885,8 @@ CREATE_SIM_OBJECT(NSGigE)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
params->min_backoff_delay = min_backoff_delay;
params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;

View file

@ -105,7 +105,7 @@ class PciDev : public DmaDevice
};
public:
struct Params : public PioDevice::Params
struct Params : public DmaDevice::Params
{
/**
* A pointer to the object that contains the first 64 bytes of

View file

@ -1199,10 +1199,7 @@ Device::transferDone()
DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
if (txEvent.scheduled())
txEvent.reschedule(curTick + cycles(1));
else
txEvent.schedule(curTick + cycles(1));
txEvent.reschedule(curTick + cycles(1), true);
}
bool
@ -1635,6 +1632,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
Param<Tick> min_backoff_delay;
Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@ -1678,6 +1677,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@ -1723,6 +1724,8 @@ CREATE_SIM_OBJECT_WNS(Sinic, SinicDevice)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
params->min_backoff_delay = min_backoff_delay;
params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;

View file

@ -68,6 +68,7 @@ Uart8250::IntrEvent::process()
DPRINTF(Uart, "UART InterEvent, interrupting\n");
uart->platform->postConsoleInt();
uart->status |= intrBit;
uart->lastTxInt = curTick;
}
else
DPRINTF(Uart, "UART InterEvent, not interrupting\n");
@ -100,14 +101,11 @@ Uart8250::IntrEvent::scheduleIntr()
Uart8250::Uart8250(Params *p)
: Uart(p), txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
: Uart(p), IER(0), DLAB(0), LCR(0), MCR(0), lastTxInt(0),
txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
{
pioSize = 8;
IER = 0;
DLAB = 0;
LCR = 0;
MCR = 0;
}
Tick
@ -153,13 +151,13 @@ Uart8250::read(PacketPtr pkt)
if (status & RX_INT) /* Rx data interrupt has a higher priority */
pkt->set(IIR_RXID);
else if (status & TX_INT)
else if (status & TX_INT) {
pkt->set(IIR_TXID);
else
//Tx interrupts are cleared on IIR reads
status &= ~TX_INT;
} else
pkt->set(IIR_NOPEND);
//Tx interrupts are cleared on IIR reads
status &= ~TX_INT;
break;
case 0x3: // Line Control Register (LCR)
pkt->set(LCR);
@ -222,7 +220,16 @@ Uart8250::write(PacketPtr pkt)
if (UART_IER_THRI & IER)
{
DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
txIntrEvent.scheduleIntr();
if (curTick - lastTxInt >
(Tick)((Clock::Float::s / 2e9) * 450)) {
DPRINTF(Uart, "-- Interrupting Immediately... %d,%d\n",
curTick, lastTxInt);
txIntrEvent.process();
} else {
DPRINTF(Uart, "-- Delaying interrupt... %d,%d\n",
curTick, lastTxInt);
txIntrEvent.scheduleIntr();
}
}
else
{

View file

@ -74,6 +74,7 @@ class Uart8250 : public Uart
protected:
uint8_t IER, DLAB, LCR, MCR;
Tick lastTxInt;
class IntrEvent : public Event
{

View file

@ -37,6 +37,7 @@
#include "kern/system_events.hh"
#include "sim/system.hh"
#include <sstream>
namespace Linux {
@ -44,15 +45,13 @@ void
DebugPrintkEvent::process(ThreadContext *tc)
{
if (DTRACE(DebugPrintf)) {
if (!raw) {
StringWrap name(tc->getSystemPtr()->name() + ".dprintk");
DPRINTFN("");
}
std::stringstream ss;
TheISA::Arguments args(tc);
Printk(args);
SkipFuncEvent::process(tc);
Printk(ss, args);
StringWrap name(tc->getSystemPtr()->name() + ".dprintk");
DPRINTFN("%s", ss.str());
}
SkipFuncEvent::process(tc);
}
} // namespace linux

View file

@ -38,13 +38,9 @@ namespace Linux {
class DebugPrintkEvent : public SkipFuncEvent
{
private:
bool raw;
public:
DebugPrintkEvent(PCEventQueue *q, const std::string &desc, Addr addr,
bool r = false)
: SkipFuncEvent(q, desc, addr), raw(r) {}
DebugPrintkEvent(PCEventQueue *q, const std::string &desc, Addr addr)
: SkipFuncEvent(q, desc, addr) {}
virtual void process(ThreadContext *xc);
};

View file

@ -32,22 +32,18 @@
#include <sys/types.h>
#include <algorithm>
#include "base/trace.hh"
#include "arch/arguments.hh"
#include "base/trace.hh"
#include "kern/linux/printk.hh"
using namespace std;
void
Printk(TheISA::Arguments args)
Printk(stringstream &out, TheISA::Arguments args)
{
std::ostream &out = Trace::output();
char *p = (char *)args++;
ios::fmtflags saved_flags = out.flags();
char old_fill = out.fill();
int old_precision = out.precision();
while (*p) {
switch (*p) {
case '%': {
@ -258,8 +254,5 @@ Printk(TheISA::Arguments args)
}
}
out.flags(saved_flags);
out.fill(old_fill);
out.precision(old_precision);
}

View file

@ -34,8 +34,10 @@
#include "arch/isa_specific.hh"
#include <sstream>
class TheISA::Arguments;
void Printk(TheISA::Arguments args);
void Printk(std::stringstream &out, TheISA::Arguments args);
#endif // __PRINTK_HH__

View file

@ -792,7 +792,7 @@ class Tru64 : public OperatingSystem
for (int i = 0; i < process->numCpus(); ++i) {
ThreadContext *tc = process->threadContexts[i];
if (tc->status() == ThreadContext::Suspended) {
if (tc->status() == ThreadContext::Unallocated) {
// inactive context... grab it
init_thread_context(tc, attrp, uniq_val);

View file

@ -43,20 +43,25 @@
Bridge::BridgePort::BridgePort(const std::string &_name,
Bridge *_bridge, BridgePort *_otherPort,
int _delay, int _queueLimit)
int _delay, int _nack_delay, int _req_limit,
int _resp_limit, bool fix_partial_write)
: Port(_name), bridge(_bridge), otherPort(_otherPort),
delay(_delay), outstandingResponses(0),
queueLimit(_queueLimit), sendEvent(this)
delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write),
outstandingResponses(0), queuedRequests(0), inRetry(false),
reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this)
{
}
Bridge::Bridge(const std::string &n, int qsa, int qsb,
Tick _delay, int write_ack)
: MemObject(n),
portA(n + "-portA", this, &portB, _delay, qsa),
portB(n + "-portB", this, &portA, _delay, qsa),
ackWrites(write_ack)
Bridge::Bridge(Params *p)
: MemObject(p->name),
portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay,
p->req_size_a, p->resp_size_a, p->fix_partial_write_a),
portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay,
p->req_size_b, p->resp_size_b, p->fix_partial_write_b),
ackWrites(p->write_ack), _params(p)
{
if (ackWrites)
panic("No support for acknowledging writes\n");
}
Port *
@ -82,35 +87,118 @@ Bridge::init()
{
// Make sure that both sides are connected to.
if (portA.getPeer() == NULL || portB.getPeer() == NULL)
panic("Both ports of bus bridge are not connected to a bus.\n");
fatal("Both ports of bus bridge are not connected to a bus.\n");
if (portA.peerBlockSize() != portB.peerBlockSize())
fatal("Busses don't have the same block size... Not supported.\n");
}
bool
Bridge::BridgePort::respQueueFull()
{
assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit);
return outstandingResponses >= respQueueLimit;
}
bool
Bridge::BridgePort::reqQueueFull()
{
assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit);
return queuedRequests >= reqQueueLimit;
}
/** Function called by the port when the bus is receiving a Timing
* transaction.*/
bool
Bridge::BridgePort::recvTiming(PacketPtr pkt)
{
if (pkt->flags & SNOOP_COMMIT) {
DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
if (!(pkt->flags & SNOOP_COMMIT))
return true;
DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr());
return otherPort->queueForSendTiming(pkt);
DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n",
sendQueue.size(), queuedRequests, outstandingResponses);
DPRINTF(BusBridge, "Remove queue size: %d outreq: %d outresp: %d\n",
otherPort->sendQueue.size(), otherPort->queuedRequests,
otherPort->outstandingResponses);
if (pkt->isRequest() && otherPort->reqQueueFull() && pkt->result !=
Packet::Nacked) {
DPRINTF(BusBridge, "Remote queue full, nacking\n");
nackRequest(pkt);
return true;
}
else {
// Else it's just a snoop, properly return if we are blocking
return !queueFull();
if (pkt->needsResponse() && pkt->result != Packet::Nacked)
if (respQueueFull()) {
DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n");
DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n",
sendQueue.size(), queuedRequests, outstandingResponses);
nackRequest(pkt);
return true;
} else {
DPRINTF(BusBridge, "Request Needs response, reserving space\n");
++outstandingResponses;
}
otherPort->queueForSendTiming(pkt);
return true;
}
void
Bridge::BridgePort::nackRequest(PacketPtr pkt)
{
// Nack the packet
pkt->result = Packet::Nacked;
pkt->setDest(pkt->getSrc());
//put it on the list to send
Tick readyTime = curTick + nackDelay;
PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true);
// nothing on the list, add it and we're done
if (sendQueue.empty()) {
assert(!sendEvent.scheduled());
sendEvent.schedule(readyTime);
sendQueue.push_back(buf);
return;
}
assert(sendEvent.scheduled() || inRetry);
// does it go at the end?
if (readyTime >= sendQueue.back()->ready) {
sendQueue.push_back(buf);
return;
}
// ok, somewhere in the middle, fun
std::list<PacketBuffer*>::iterator i = sendQueue.begin();
std::list<PacketBuffer*>::iterator end = sendQueue.end();
std::list<PacketBuffer*>::iterator begin = sendQueue.begin();
bool done = false;
while (i != end && !done) {
if (readyTime < (*i)->ready) {
if (i == begin)
sendEvent.reschedule(readyTime);
sendQueue.insert(i,buf);
done = true;
}
i++;
}
assert(done);
}
bool
void
Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
{
if (queueFull())
return false;
if (pkt->isResponse()) {
if (pkt->isResponse() || pkt->result == Packet::Nacked) {
// This is a response for a request we forwarded earlier. The
// corresponding PacketBuffer should be stored in the packet's
// senderState field.
@ -119,12 +207,26 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
// set up new packet dest & senderState based on values saved
// from original request
buf->fixResponse(pkt);
// Check if this packet was expecting a response and it's a nacked
// packet, in which case we will never being seeing it
if (buf->expectResponse && pkt->result == Packet::Nacked)
--outstandingResponses;
DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n",
pkt->senderState, buf);
DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
delete buf;
}
if (pkt->isRequest() && pkt->result != Packet::Nacked) {
++queuedRequests;
}
Tick readyTime = curTick + delay;
PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n",
@ -137,10 +239,7 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
if (sendQueue.empty()) {
sendEvent.schedule(readyTime);
}
sendQueue.push_back(buf);
return true;
}
void
@ -148,28 +247,38 @@ Bridge::BridgePort::trySend()
{
assert(!sendQueue.empty());
bool was_full = queueFull();
PacketBuffer *buf = sendQueue.front();
assert(buf->ready <= curTick);
PacketPtr pkt = buf->pkt;
pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set
// Ugly! @todo When multilevel coherence works this will be removed
if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite &&
pkt->result != Packet::Nacked) {
PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
Packet::Broadcast);
funcPkt->dataStatic(pkt->getPtr<uint8_t>());
sendFunctional(funcPkt);
pkt->cmd = MemCmd::WriteReq;
delete funcPkt;
}
DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
buf->origSrc, pkt->getDest(), pkt->getAddr());
pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set
bool wasReq = pkt->isRequest();
bool wasNacked = pkt->result == Packet::Nacked;
if (sendTiming(pkt)) {
// send successful
sendQueue.pop_front();
buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
if (buf->expectResponse) {
// Must wait for response. We just need to count outstanding
// responses (in case we want to cap them); PacketBuffer
// pointer will be recovered on response.
++outstandingResponses;
// Must wait for response
DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
outstandingResponses);
} else {
@ -178,27 +287,37 @@ Bridge::BridgePort::trySend()
delete buf;
}
if (!wasNacked) {
if (wasReq)
--queuedRequests;
else
--outstandingResponses;
}
// If there are more packets to send, schedule event to try again.
if (!sendQueue.empty()) {
buf = sendQueue.front();
DPRINTF(BusBridge, "Scheduling next send\n");
sendEvent.schedule(std::max(buf->ready, curTick + 1));
}
// Let things start sending again
if (was_full) {
DPRINTF(BusBridge, "Queue was full, sending retry\n");
otherPort->sendRetry();
}
} else {
DPRINTF(BusBridge, " unsuccessful\n");
inRetry = true;
}
DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n",
sendQueue.size(), queuedRequests, outstandingResponses);
}
void
Bridge::BridgePort::recvRetry()
{
trySend();
inRetry = false;
Tick nextReady = sendQueue.front()->ready;
if (nextReady <= curTick)
trySend();
else
sendEvent.schedule(nextReady);
}
/** Function called by the port when the bus is receiving a Atomic
@ -206,7 +325,18 @@ Bridge::BridgePort::recvRetry()
Tick
Bridge::BridgePort::recvAtomic(PacketPtr pkt)
{
return otherPort->sendAtomic(pkt) + delay;
// fix partial atomic writes... similar to the timing code that does the
// same... will be removed once our code gets this right
if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite) {
PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
Packet::Broadcast);
funcPkt->dataStatic(pkt->getPtr<uint8_t>());
otherPort->sendFunctional(funcPkt);
delete funcPkt;
pkt->cmd = MemCmd::WriteReq;
}
return delay + otherPort->sendAtomic(pkt);
}
/** Function called by the port when the bus is receiving a Functional
@ -244,26 +374,48 @@ Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
Param<int> queue_size_a;
Param<int> queue_size_b;
Param<int> req_size_a;
Param<int> req_size_b;
Param<int> resp_size_a;
Param<int> resp_size_b;
Param<Tick> delay;
Param<Tick> nack_delay;
Param<bool> write_ack;
Param<bool> fix_partial_write_a;
Param<bool> fix_partial_write_b;
END_DECLARE_SIM_OBJECT_PARAMS(Bridge)
BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge)
INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"),
INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"),
INIT_PARAM(req_size_a, "The size of the queue for requests coming into side a"),
INIT_PARAM(req_size_b, "The size of the queue for requests coming into side b"),
INIT_PARAM(resp_size_a, "The size of the queue for responses coming into side a"),
INIT_PARAM(resp_size_b, "The size of the queue for responses coming into side b"),
INIT_PARAM(delay, "The miminum delay to cross this bridge"),
INIT_PARAM(write_ack, "Acknowledge any writes that are received.")
INIT_PARAM(nack_delay, "The minimum delay to nack a packet"),
INIT_PARAM(write_ack, "Acknowledge any writes that are received."),
INIT_PARAM(fix_partial_write_a, "Fixup any partial block writes that are received"),
INIT_PARAM(fix_partial_write_b, "Fixup any partial block writes that are received")
END_INIT_SIM_OBJECT_PARAMS(Bridge)
CREATE_SIM_OBJECT(Bridge)
{
return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay,
write_ack);
Bridge::Params *p = new Bridge::Params;
p->name = getInstanceName();
p->req_size_a = req_size_a;
p->req_size_b = req_size_b;
p->resp_size_a = resp_size_a;
p->resp_size_b = resp_size_b;
p->delay = delay;
p->nack_delay = nack_delay;
p->write_ack = write_ack;
p->fix_partial_write_a = fix_partial_write_a;
p->fix_partial_write_b = fix_partial_write_b;
return new Bridge(p);
}
REGISTER_SIM_OBJECT("Bridge", Bridge)

View file

@ -66,6 +66,11 @@ class Bridge : public MemObject
/** Minimum delay though this bridge. */
Tick delay;
/** Min delay to respond to a nack. */
Tick nackDelay;
bool fixPartialWrite;
class PacketBuffer : public Packet::SenderState {
public:
@ -75,12 +80,13 @@ class Bridge : public MemObject
short origSrc;
bool expectResponse;
PacketBuffer(PacketPtr _pkt, Tick t)
PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false)
: ready(t), pkt(_pkt),
origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
expectResponse(_pkt->needsResponse())
expectResponse(_pkt->needsResponse() && !nack)
{
if (!pkt->isResponse())
if (!pkt->isResponse() && !nack && pkt->result != Packet::Nacked)
pkt->senderState = this;
}
@ -100,19 +106,29 @@ class Bridge : public MemObject
std::list<PacketBuffer*> sendQueue;
int outstandingResponses;
int queuedRequests;
/** If we're waiting for a retry to happen.*/
bool inRetry;
/** Max queue size for outbound packets */
int queueLimit;
int reqQueueLimit;
/** Max queue size for reserved responses. */
int respQueueLimit;
/**
* Is this side blocked from accepting outbound packets?
*/
bool queueFull() { return (sendQueue.size() == queueLimit); }
bool respQueueFull();
bool reqQueueFull();
bool queueForSendTiming(PacketPtr pkt);
void queueForSendTiming(PacketPtr pkt);
void finishSend(PacketBuffer *buf);
void nackRequest(PacketPtr pkt);
/**
* Handle send event, scheduled when the packet at the head of
* the outbound queue is ready to transmit (for timing
@ -136,11 +152,10 @@ class Bridge : public MemObject
SendEvent sendEvent;
public:
/** Constructor for the BusPort.*/
BridgePort(const std::string &_name,
Bridge *_bridge, BridgePort *_otherPort,
int _delay, int _queueLimit);
BridgePort(const std::string &_name, Bridge *_bridge,
BridgePort *_otherPort, int _delay, int _nack_delay,
int _req_limit, int _resp_limit, bool fix_partial_write);
protected:
@ -176,13 +191,32 @@ class Bridge : public MemObject
bool ackWrites;
public:
struct Params
{
std::string name;
int req_size_a;
int req_size_b;
int resp_size_a;
int resp_size_b;
Tick delay;
Tick nack_delay;
bool write_ack;
bool fix_partial_write_a;
bool fix_partial_write_b;
};
protected:
Params *_params;
public:
const Params *params() const { return _params; }
/** A function used to return the port associated with this bus object. */
virtual Port *getPort(const std::string &if_name, int idx = -1);
virtual void init();
Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack);
Bridge(Params *p);
};
#endif //__MEM_BUS_HH__

View file

@ -48,6 +48,7 @@ Bus::getPort(const std::string &if_name, int idx)
if (defaultPort == NULL) {
defaultPort = new BusPort(csprintf("%s-default",name()), this,
defaultId);
cachedBlockSizeValid = false;
return defaultPort;
} else
fatal("Default port already set\n");
@ -68,6 +69,7 @@ Bus::getPort(const std::string &if_name, int idx)
assert(maxId < std::numeric_limits<typeof(maxId)>::max());
BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
interfaces[id] = bp;
cachedBlockSizeValid = false;
return bp;
}
@ -169,8 +171,9 @@ bool
Bus::recvTiming(PacketPtr pkt)
{
Port *port;
DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s result %d\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString(),
pkt->result);
BusPort *pktPort;
if (pkt->getSrc() == defaultId)
@ -182,6 +185,7 @@ Bus::recvTiming(PacketPtr pkt)
if (tickNextIdle > curTick ||
(retryList.size() && (!inRetry || pktPort != retryList.front()))) {
addToRetryList(pktPort);
DPRINTF(Bus, "recvTiming: Bus is busy, returning false\n");
return false;
}
@ -207,11 +211,12 @@ Bus::recvTiming(PacketPtr pkt)
inRetry = false;
}
occupyBus(pkt);
DPRINTF(Bus, "recvTiming: Packet sucessfully sent\n");
return true;
}
} else {
//Snoop didn't succeed
DPRINTF(Bus, "Adding a retry to RETRY list %d\n",
DPRINTF(Bus, "Adding1 a retry to RETRY list %d\n",
pktPort->getId());
addToRetryList(pktPort);
return false;
@ -239,13 +244,14 @@ Bus::recvTiming(PacketPtr pkt)
}
// Packet not successfully sent. Leave or put it on the retry list.
DPRINTF(Bus, "Adding a retry to RETRY list %d\n",
DPRINTF(Bus, "Adding2 a retry to RETRY list %d\n",
pktPort->getId());
addToRetryList(pktPort);
return false;
}
else {
//Forwarding up from responder, just return true;
DPRINTF(Bus, "recvTiming: can we be here?\n");
return true;
}
}
@ -253,12 +259,12 @@ Bus::recvTiming(PacketPtr pkt)
void
Bus::recvRetry(int id)
{
DPRINTF(Bus, "Received a retry\n");
DPRINTF(Bus, "Received a retry from %s\n", id == -1 ? "self" : interfaces[id]->getPeer()->name());
// If there's anything waiting, and the bus isn't busy...
if (retryList.size() && curTick >= tickNextIdle) {
//retryingPort = retryList.front();
inRetry = true;
DPRINTF(Bus, "Sending a retry\n");
DPRINTF(Bus, "Sending a retry to %s\n", retryList.front()->getPeer()->name());
retryList.front()->sendRetry();
// If inRetry is still true, sendTiming wasn't called
if (inRetry)
@ -274,11 +280,7 @@ Bus::recvRetry(int id)
//Burn a cycle for the missed grant.
tickNextIdle += clock;
if (!busIdle.scheduled()) {
busIdle.schedule(tickNextIdle);
} else {
busIdle.reschedule(tickNextIdle);
}
busIdle.reschedule(tickNextIdle, true);
}
}
//If we weren't able to drain before, we might be able to now.
@ -598,6 +600,37 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
}
}
int
Bus::findBlockSize(int id)
{
if (cachedBlockSizeValid)
return cachedBlockSize;
int max_bs = -1, tmp_bs;
range_map<Addr,int>::iterator portIter;
std::vector<DevMap>::iterator snoopIter;
for (portIter = portMap.begin(); portIter != portMap.end(); portIter++) {
tmp_bs = interfaces[portIter->second]->peerBlockSize();
if (tmp_bs > max_bs)
max_bs = tmp_bs;
}
for (snoopIter = portSnoopList.begin();
snoopIter != portSnoopList.end(); snoopIter++) {
tmp_bs = interfaces[snoopIter->portId]->peerBlockSize();
if (tmp_bs > max_bs)
max_bs = tmp_bs;
}
if (max_bs <= 0)
max_bs = defaultBlockSize;
if (max_bs != 64)
warn_once("Blocksize found to not be 64... hmm... probably not.\n");
cachedBlockSize = max_bs;
cachedBlockSizeValid = true;
return max_bs;
}
unsigned int
Bus::drain(Event * de)
{
@ -618,6 +651,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
Param<int> clock;
Param<int> width;
Param<bool> responder_set;
Param<int> block_size;
END_DECLARE_SIM_OBJECT_PARAMS(Bus)
@ -625,12 +659,14 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Bus)
INIT_PARAM(bus_id, "a globally unique bus id"),
INIT_PARAM(clock, "bus clock speed"),
INIT_PARAM(width, "width of the bus (bits)"),
INIT_PARAM(responder_set, "Is a default responder set by the user")
INIT_PARAM(responder_set, "Is a default responder set by the user"),
INIT_PARAM(block_size, "Default blocksize if no device has one")
END_INIT_SIM_OBJECT_PARAMS(Bus)
CREATE_SIM_OBJECT(Bus)
{
return new Bus(getInstanceName(), bus_id, clock, width, responder_set);
return new Bus(getInstanceName(), bus_id, clock, width, responder_set,
block_size);
}
REGISTER_SIM_OBJECT("Bus", Bus)

View file

@ -133,6 +133,12 @@ class Bus : public MemObject
/** Occupy the bus with transmitting the packet pkt */
void occupyBus(PacketPtr pkt);
/** Ask everyone on the bus what their size is
* @param id id of the busport that made the request
* @return the max of all the sizes
*/
int findBlockSize(int id);
/** Declaration of the buses port type, one will be instantiated for each
of the interfaces connecting to the bus. */
class BusPort : public Port
@ -195,8 +201,11 @@ class Bus : public MemObject
AddrRangeList &snoop)
{ bus->addressRanges(resp, snoop, id); }
// Hack to make translating port work without changes
virtual int deviceBlockSize() { return 32; }
// Ask the bus to ask everyone on the bus what their block size is and
// take the max of it. This might need to be changed a bit if we ever
// support multiple block sizes.
virtual int deviceBlockSize()
{ return bus->findBlockSize(id); }
};
@ -256,6 +265,10 @@ class Bus : public MemObject
/** Has the user specified their own default responder? */
bool responderSet;
int defaultBlockSize;
int cachedBlockSize;
bool cachedBlockSizeValid;
public:
/** A function used to return the port associated with this bus object. */
@ -267,11 +280,12 @@ class Bus : public MemObject
unsigned int drain(Event *de);
Bus(const std::string &n, int bus_id, int _clock, int _width,
bool responder_set)
bool responder_set, int dflt_blk_size)
: MemObject(n), busId(bus_id), clock(_clock), width(_width),
tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4),
responderSet(responder_set)
responderSet(responder_set), defaultBlockSize(dflt_blk_size),
cachedBlockSize(0), cachedBlockSizeValid(false)
{
//Both the width and clock period must be positive
if (width <= 0)

View file

@ -134,8 +134,7 @@ BaseCache::CachePort::recvRetry()
isCpuSide && cache->doSlaveRequest()) {
DPRINTF(CachePort, "%s has more responses/requests\n", name());
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false);
reqCpu->schedule(curTick + 1);
new BaseCache::RequestEvent(this, curTick + 1);
}
waitingOnRetry = false;
}
@ -178,8 +177,7 @@ BaseCache::CachePort::recvRetry()
{
DPRINTF(CachePort, "%s has more requests\n", name());
//Still more to issue, rerequest in 1 cycle
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false);
reqCpu->schedule(curTick + 1);
new BaseCache::RequestEvent(this, curTick + 1);
}
}
else
@ -196,8 +194,7 @@ BaseCache::CachePort::recvRetry()
{
DPRINTF(CachePort, "%s has more requests\n", name());
//Still more to issue, rerequest in 1 cycle
BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this, false);
reqCpu->schedule(curTick + 1);
new BaseCache::RequestEvent(this, curTick + 1);
}
}
if (waitingOnRetry) DPRINTF(CachePort, "%s STILL Waiting on retry\n", name());
@ -228,102 +225,109 @@ BaseCache::CachePort::clearBlocked()
}
}
BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, bool _newResponse)
: Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort),
newResponse(_newResponse)
BaseCache::RequestEvent::RequestEvent(CachePort *_cachePort, Tick when)
: Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort)
{
if (!newResponse)
this->setFlags(AutoDelete);
pkt = NULL;
this->setFlags(AutoDelete);
schedule(when);
}
void
BaseCache::CacheEvent::process()
BaseCache::RequestEvent::process()
{
if (!newResponse)
{
if (cachePort->waitingOnRetry) return;
//We have some responses to drain first
if (!cachePort->drainList.empty()) {
DPRINTF(CachePort, "%s trying to drain a response\n", cachePort->name());
if (cachePort->sendTiming(cachePort->drainList.front())) {
DPRINTF(CachePort, "%s drains a response succesfully\n", cachePort->name());
cachePort->drainList.pop_front();
if (!cachePort->drainList.empty() ||
!cachePort->isCpuSide && cachePort->cache->doMasterRequest() ||
cachePort->isCpuSide && cachePort->cache->doSlaveRequest()) {
if (cachePort->waitingOnRetry) return;
//We have some responses to drain first
if (!cachePort->drainList.empty()) {
DPRINTF(CachePort, "%s trying to drain a response\n", cachePort->name());
if (cachePort->sendTiming(cachePort->drainList.front())) {
DPRINTF(CachePort, "%s drains a response succesfully\n", cachePort->name());
cachePort->drainList.pop_front();
if (!cachePort->drainList.empty() ||
!cachePort->isCpuSide && cachePort->cache->doMasterRequest() ||
cachePort->isCpuSide && cachePort->cache->doSlaveRequest()) {
DPRINTF(CachePort, "%s still has outstanding bus reqs\n", cachePort->name());
this->schedule(curTick + 1);
}
}
else {
cachePort->waitingOnRetry = true;
DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
DPRINTF(CachePort, "%s still has outstanding bus reqs\n", cachePort->name());
this->schedule(curTick + 1);
}
}
else if (!cachePort->isCpuSide)
{ //MSHR
DPRINTF(CachePort, "%s trying to send a MSHR request\n", cachePort->name());
if (!cachePort->cache->doMasterRequest()) {
//This can happen if I am the owner of a block and see an upgrade
//while the block was in my WB Buffers. I just remove the
//wb and de-assert the masterRequest
return;
}
pkt = cachePort->cache->getPacket();
MSHR* mshr = (MSHR*) pkt->senderState;
//Copy the packet, it may be modified/destroyed elsewhere
PacketPtr copyPkt = new Packet(*pkt);
copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
mshr->pkt = copyPkt;
bool success = cachePort->sendTiming(pkt);
DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
pkt->getAddr(), success ? "succesful" : "unsuccesful");
cachePort->waitingOnRetry = !success;
if (cachePort->waitingOnRetry) {
DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
}
cachePort->cache->sendResult(pkt, mshr, success);
if (success && cachePort->cache->doMasterRequest())
{
DPRINTF(CachePort, "%s still more MSHR requests to send\n",
cachePort->name());
//Still more to issue, rerequest in 1 cycle
pkt = NULL;
this->schedule(curTick+1);
}
else {
cachePort->waitingOnRetry = true;
DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
}
else
{
//CSHR
assert(cachePort->cache->doSlaveRequest());
pkt = cachePort->cache->getCoherencePacket();
MSHR* cshr = (MSHR*) pkt->senderState;
bool success = cachePort->sendTiming(pkt);
cachePort->cache->sendCoherenceResult(pkt, cshr, success);
cachePort->waitingOnRetry = !success;
if (cachePort->waitingOnRetry)
DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
if (success && cachePort->cache->doSlaveRequest())
{
DPRINTF(CachePort, "%s still more CSHR requests to send\n",
cachePort->name());
//Still more to issue, rerequest in 1 cycle
pkt = NULL;
this->schedule(curTick+1);
}
}
return;
}
//Else it's a response
else if (!cachePort->isCpuSide)
{ //MSHR
DPRINTF(CachePort, "%s trying to send a MSHR request\n", cachePort->name());
if (!cachePort->cache->doMasterRequest()) {
//This can happen if I am the owner of a block and see an upgrade
//while the block was in my WB Buffers. I just remove the
//wb and de-assert the masterRequest
return;
}
PacketPtr pkt = cachePort->cache->getPacket();
MSHR* mshr = (MSHR*) pkt->senderState;
//Copy the packet, it may be modified/destroyed elsewhere
PacketPtr copyPkt = new Packet(*pkt);
copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
mshr->pkt = copyPkt;
bool success = cachePort->sendTiming(pkt);
DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
pkt->getAddr(), success ? "succesful" : "unsuccesful");
cachePort->waitingOnRetry = !success;
if (cachePort->waitingOnRetry) {
DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
}
cachePort->cache->sendResult(pkt, mshr, success);
if (success && cachePort->cache->doMasterRequest())
{
DPRINTF(CachePort, "%s still more MSHR requests to send\n",
cachePort->name());
//Still more to issue, rerequest in 1 cycle
this->schedule(curTick+1);
}
}
else
{
//CSHR
assert(cachePort->cache->doSlaveRequest());
PacketPtr pkt = cachePort->cache->getCoherencePacket();
MSHR* cshr = (MSHR*) pkt->senderState;
bool success = cachePort->sendTiming(pkt);
cachePort->cache->sendCoherenceResult(pkt, cshr, success);
cachePort->waitingOnRetry = !success;
if (cachePort->waitingOnRetry)
DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
if (success && cachePort->cache->doSlaveRequest())
{
DPRINTF(CachePort, "%s still more CSHR requests to send\n",
cachePort->name());
//Still more to issue, rerequest in 1 cycle
this->schedule(curTick+1);
}
}
}
const char *
BaseCache::RequestEvent::description()
{
return "Cache request event";
}
BaseCache::ResponseEvent::ResponseEvent(CachePort *_cachePort)
: Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort)
{
}
void
BaseCache::ResponseEvent::process()
{
assert(cachePort->transmitList.size());
assert(cachePort->transmitList.front().first <= curTick);
pkt = cachePort->transmitList.front().second;
PacketPtr pkt = cachePort->transmitList.front().second;
cachePort->transmitList.pop_front();
if (!cachePort->transmitList.empty()) {
Tick time = cachePort->transmitList.front().first;
@ -354,9 +358,9 @@ BaseCache::CacheEvent::process()
}
const char *
BaseCache::CacheEvent::description()
BaseCache::ResponseEvent::description()
{
return "BaseCache timing event";
return "Cache response event";
}
void

View file

@ -117,13 +117,20 @@ class BaseCache : public MemObject
std::list<std::pair<Tick,PacketPtr> > transmitList;
};
struct CacheEvent : public Event
struct RequestEvent : public Event
{
CachePort *cachePort;
PacketPtr pkt;
bool newResponse;
CacheEvent(CachePort *_cachePort, bool response);
RequestEvent(CachePort *_cachePort, Tick when);
void process();
const char *description();
};
struct ResponseEvent : public Event
{
CachePort *cachePort;
ResponseEvent(CachePort *_cachePort);
void process();
const char *description();
};
@ -132,8 +139,8 @@ class BaseCache : public MemObject
CachePort *cpuSidePort;
CachePort *memSidePort;
CacheEvent *sendEvent;
CacheEvent *memSendEvent;
ResponseEvent *sendEvent;
ResponseEvent *memSendEvent;
private:
void recvStatusChange(Port::Status status, bool isCpuSide)
@ -432,9 +439,7 @@ class BaseCache : public MemObject
{
if (!doMasterRequest() && !memSidePort->waitingOnRetry)
{
BaseCache::CacheEvent * reqCpu =
new BaseCache::CacheEvent(memSidePort, false);
reqCpu->schedule(time);
new RequestEvent(memSidePort, time);
}
uint8_t flag = 1<<cause;
masterRequests |= flag;
@ -469,9 +474,7 @@ class BaseCache : public MemObject
{
if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry)
{
BaseCache::CacheEvent * reqCpu =
new BaseCache::CacheEvent(cpuSidePort, false);
reqCpu->schedule(time);
new RequestEvent(cpuSidePort, time);
}
uint8_t flag = 1<<cause;
slaveRequests |= flag;

View file

@ -134,7 +134,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(BaseCache)
Param<bool> prefetch_cache_check_push;
Param<bool> prefetch_use_cpu_id;
Param<bool> prefetch_data_accesses_only;
Param<int> hit_latency;
END_DECLARE_SIM_OBJECT_PARAMS(BaseCache)
@ -190,8 +189,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(BaseCache)
INIT_PARAM_DFLT(prefetch_policy, "Type of prefetcher to use", "none"),
INIT_PARAM_DFLT(prefetch_cache_check_push, "Check if in cash on push or pop of prefetch queue", true),
INIT_PARAM_DFLT(prefetch_use_cpu_id, "Use the CPU ID to seperate calculations of prefetches", true),
INIT_PARAM_DFLT(prefetch_data_accesses_only, "Only prefetch on data not on instruction accesses", false),
INIT_PARAM_DFLT(hit_latency, "Hit Latecny for a succesful access", 1)
INIT_PARAM_DFLT(prefetch_data_accesses_only, "Only prefetch on data not on instruction accesses", false)
END_INIT_SIM_OBJECT_PARAMS(BaseCache)
@ -211,7 +209,7 @@ END_INIT_SIM_OBJECT_PARAMS(BaseCache)
BUILD_NULL_PREFETCHER(TAGS); \
} \
Cache<TAGS, c>::Params params(tags, mq, coh, base_params, \
pf, prefetch_access, hit_latency, \
pf, prefetch_access, latency, \
true, \
store_compressed, \
adaptive_compression, \

View file

@ -1146,11 +1146,11 @@ template<class TagStore, class Coherence>
Port *
Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx)
{
if (if_name == "")
if (if_name == "" || if_name == "cpu_side")
{
if (cpuSidePort == NULL) {
cpuSidePort = new CpuSidePort(name() + "-cpu_side_port", this);
sendEvent = new CacheEvent(cpuSidePort, true);
sendEvent = new ResponseEvent(cpuSidePort);
}
return cpuSidePort;
}
@ -1158,20 +1158,12 @@ Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx)
{
return new CpuSidePort(name() + "-cpu_side_funcport", this);
}
else if (if_name == "cpu_side")
{
if (cpuSidePort == NULL) {
cpuSidePort = new CpuSidePort(name() + "-cpu_side_port", this);
sendEvent = new CacheEvent(cpuSidePort, true);
}
return cpuSidePort;
}
else if (if_name == "mem_side")
{
if (memSidePort != NULL)
panic("Already have a mem side for this cache\n");
memSidePort = new MemSidePort(name() + "-mem_side_port", this);
memSendEvent = new CacheEvent(memSidePort, true);
memSendEvent = new ResponseEvent(memSidePort);
return memSidePort;
}
else panic("Port name %s unrecognized\n", if_name);
@ -1192,6 +1184,8 @@ template<class TagStore, class Coherence>
bool
Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt)
{
assert(pkt->result != Packet::Nacked);
if (!pkt->req->isUncacheable()
&& pkt->isInvalidate()
&& !pkt->isRead() && !pkt->isWrite()) {
@ -1249,6 +1243,12 @@ template<class TagStore, class Coherence>
bool
Cache<TagStore,Coherence>::MemSidePort::recvTiming(PacketPtr pkt)
{
// this needs to be fixed so that the cache updates the mshr and sends the
// packet back out on the link, but it probably won't happen so until this
// gets fixed, just panic when it does
if (pkt->result == Packet::Nacked)
panic("Need to implement cache resending nacked packets!\n");
if (pkt->isRequest() && blocked)
{
DPRINTF(Cache,"Scheduling a retry while blocked\n");
@ -1282,9 +1282,9 @@ template<class TagStore, class Coherence>
void
Cache<TagStore,Coherence>::MemSidePort::recvFunctional(PacketPtr pkt)
{
if (checkFunctional(pkt)) {
myCache()->probe(pkt, false, cache->cpuSidePort);
}
myCache()->probe(pkt, false, cache->cpuSidePort);
if (pkt->result != Packet::Success)
checkFunctional(pkt);
}

View file

@ -85,7 +85,7 @@ MemCmd::commandInfo[] =
{ SET5(IsWrite, IsInvalidate, IsRequest, HasData, NeedsResponse),
WriteInvalidateResp, "WriteInvalidateReq" },
/* WriteInvalidateResp */
{ SET5(IsWrite, IsInvalidate, IsRequest, NeedsResponse, IsResponse),
{ SET3(IsWrite, IsInvalidate, IsResponse),
InvalidCmd, "WriteInvalidateResp" },
/* UpgradeReq */
{ SET3(IsInvalidate, IsRequest, IsUpgrade), InvalidCmd, "UpgradeReq" },

View file

@ -161,10 +161,10 @@ class Port
/** Called by a peer port in order to determine the block size of the
device connected to this port. It sometimes doesn't make sense for
this function to be called, a DMA interface doesn't really have a
block size, so it is defaulted to a panic.
this function to be called, so it just returns 0. Anytthing that is
concerned with the size should just ignore that.
*/
virtual int deviceBlockSize() { panic("??"); M5_DUMMY_RETURN }
virtual int deviceBlockSize() { return 0; }
/** The peer port is requesting us to reply with a list of the ranges we
are responsible for.

View file

@ -128,6 +128,7 @@ SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
}
i++;
}
assert(done);
}
void

View file

@ -34,12 +34,14 @@
#include "mem/port.hh"
#include "mem/translating_port.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
using namespace TheISA;
TranslatingPort::TranslatingPort(const std::string &_name,
PageTable *p_table, bool alloc)
: FunctionalPort(_name), pTable(p_table), allocating(alloc)
Process *p, AllocType alloc)
: FunctionalPort(_name), pTable(p->pTable), process(p),
allocating(alloc)
{ }
TranslatingPort::~TranslatingPort()
@ -81,13 +83,18 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size)
for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
if (!pTable->translate(gen.addr(), paddr)) {
if (allocating) {
if (allocating == Always) {
pTable->allocate(roundDown(gen.addr(), VMPageSize),
VMPageSize);
pTable->translate(gen.addr(), paddr);
} else if (allocating == NextPage) {
// check if we've accessed the next page on the stack
if (!process->checkAndAllocNextPage(gen.addr()))
panic("Page table fault when accessing virtual address %#x "
"during functional write\n", gen.addr());
} else {
return false;
}
pTable->translate(gen.addr(), paddr);
}
Port::writeBlob(paddr, p + prevSize, gen.size());
@ -113,7 +120,7 @@ TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size)
for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
if (!pTable->translate(gen.addr(), paddr)) {
if (allocating) {
if (allocating == Always) {
pTable->allocate(roundDown(gen.addr(), VMPageSize),
VMPageSize);
pTable->translate(gen.addr(), paddr);

View file

@ -35,16 +35,25 @@
#include "mem/port.hh"
class PageTable;
class Process;
class TranslatingPort : public FunctionalPort
{
public:
enum AllocType {
Always,
Never,
NextPage
};
private:
PageTable *pTable;
bool allocating;
Process *process;
AllocType allocating;
public:
TranslatingPort(const std::string &_name,
PageTable *p_table, bool alloc = false);
Process *p, AllocType alloc);
virtual ~TranslatingPort();
bool tryReadBlob(Addr addr, uint8_t *p, int size);

View file

@ -30,129 +30,84 @@
# Nathan Binkert
import os
import zipfile
# handy function for path joins
def join(*args):
return os.path.normpath(os.path.join(*args))
Import('*')
# This SConscript is in charge of collecting .py files and generating
# a zip archive that is appended to the m5 binary.
# List of files & directories to include in the zip file. To include
# a package, list only the root directory of the package, not any
# internal .py files (else they will get the path stripped off when
# they are imported into the zip file).
pyzip_files = []
# List of additional files on which the zip archive depends, but which
# are not included in pyzip_files... i.e. individual .py files within
# a package.
pyzip_dep_files = []
# Add the specified package to the zip archive. Adds the directory to
# pyzip_files and all included .py files to pyzip_dep_files.
def addPkg(pkgdir):
pyzip_files.append(pkgdir)
origdir = os.getcwd()
srcdir = join(Dir('.').srcnode().abspath, pkgdir)
os.chdir(srcdir)
for path, dirs, files in os.walk('.'):
for i,dir in enumerate(dirs):
if dir == 'SCCS':
del dirs[i]
break
for f in files:
if f.endswith('.py'):
pyzip_dep_files.append(join(pkgdir, path, f))
os.chdir(origdir)
# Generate Python file that contains a dict specifying the current
# build_env flags.
def MakeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
print >>f, "m5_build_env = ", source[0]
f.close()
optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
env.Command('m5/defines.py', Value(optionDict), MakeDefinesPyFile)
def MakeInfoPyFile(target, source, env):
f = file(str(target[0]), 'w')
for src in source:
data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
print >>f, "%s = %s" % (src, repr(data))
f.close()
env.Command('m5/info.py',
[ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
MakeInfoPyFile)
# Now specify the packages & files for the zip archive.
addPkg('m5')
pyzip_files.append('m5/defines.py')
pyzip_files.append('m5/info.py')
pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py'))
pyzip_files.append(join(env['ROOT'], 'src/base/traceflags.py'))
swig_modules = []
def swig_it(module):
env.Command(['swig/%s_wrap.cc' % module, 'm5/internal/%s.py' % module],
'swig/%s.i' % module,
'$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
'-o ${TARGETS[0]} $SOURCES')
swig_modules.append(module)
Source('swig/%s_wrap.cc' % module)
Source('swig/init.cc')
Source('swig/pyevent.cc')
Source('swig/pyobject.cc')
swig_it('core')
swig_it('debug')
swig_it('event')
swig_it('random')
swig_it('sim_object')
swig_it('stats')
swig_it('trace')
PySource('m5', 'm5/__init__.py')
PySource('m5', 'm5/SimObject.py')
PySource('m5', 'm5/attrdict.py')
PySource('m5', 'm5/convert.py')
PySource('m5', 'm5/event.py')
PySource('m5', 'm5/main.py')
PySource('m5', 'm5/multidict.py')
PySource('m5', 'm5/params.py')
PySource('m5', 'm5/proxy.py')
PySource('m5', 'm5/smartdict.py')
PySource('m5', 'm5/stats.py')
PySource('m5', 'm5/ticks.py')
PySource('m5', 'm5/util.py')
# Automatically generate m5/internals/__init__.py
def MakeInternalsInit(target, source, env):
f = file(str(target[0]), 'w')
for m in swig_modules:
print >>f, 'import %s' % m
f.close()
PySource('m5', os.path.join(env['ROOT'], 'util/pbs/jobfile.py'))
swig_py_files = [ 'm5/internal/%s.py' % m for m in swig_modules ]
env.Command('m5/internal/__init__.py', swig_py_files, MakeInternalsInit)
pyzip_dep_files.append('m5/internal/__init__.py')
SwigSource('m5.internal', 'swig/core.i')
SwigSource('m5.internal', 'swig/debug.i')
SwigSource('m5.internal', 'swig/event.i')
SwigSource('m5.internal', 'swig/random.i')
SwigSource('m5.internal', 'swig/sim_object.i')
SwigSource('m5.internal', 'swig/stats.i')
SwigSource('m5.internal', 'swig/trace.i')
PySource('m5.internal', 'm5/internal/__init__.py')
def MakeSwigInit(target, source, env):
f = file(str(target[0]), 'w')
print >>f, 'extern "C" {'
for m in swig_modules:
print >>f, ' void init_%s();' % m
print >>f, '}'
print >>f, 'void init_swig() {'
for m in swig_modules:
print >>f, ' init_%s();' % m
print >>f, '}'
f.close()
swig_cc_files = [ 'swig/%s_wrap.cc' % m for m in swig_modules ]
env.Command('swig/init.cc', swig_cc_files, MakeSwigInit)
# Action function to build the zip archive. Uses the PyZipFile module
# included in the standard Python library.
def buildPyZip(target, source, env):
pzf = zipfile.PyZipFile(str(target[0]), 'w')
for s in source:
pzf.writepy(str(s))
# Add the zip file target to the environment.
env.Command('m5py.zip', pyzip_files, buildPyZip)
env.Depends('m5py.zip', pyzip_dep_files)
SimObject('m5/objects/AlphaConsole.py')
SimObject('m5/objects/AlphaTLB.py')
SimObject('m5/objects/BadDevice.py')
SimObject('m5/objects/BaseCPU.py')
SimObject('m5/objects/BaseCache.py')
SimObject('m5/objects/BaseHier.py')
SimObject('m5/objects/BaseMem.py')
SimObject('m5/objects/BaseMemory.py')
SimObject('m5/objects/BranchPred.py')
SimObject('m5/objects/Bridge.py')
SimObject('m5/objects/Bus.py')
SimObject('m5/objects/Checker.py')
SimObject('m5/objects/CoherenceProtocol.py')
SimObject('m5/objects/DRAMMemory.py')
SimObject('m5/objects/Device.py')
SimObject('m5/objects/DiskImage.py')
SimObject('m5/objects/Ethernet.py')
SimObject('m5/objects/FUPool.py')
SimObject('m5/objects/FastCPU.py')
#SimObject('m5/objects/FreebsdSystem.py')
SimObject('m5/objects/FuncUnit.py')
SimObject('m5/objects/FuncUnitConfig.py')
SimObject('m5/objects/FunctionalMemory.py')
SimObject('m5/objects/HierParams.py')
SimObject('m5/objects/Ide.py')
SimObject('m5/objects/IntrControl.py')
SimObject('m5/objects/LinuxSystem.py')
SimObject('m5/objects/MainMemory.py')
SimObject('m5/objects/MemObject.py')
SimObject('m5/objects/MemTest.py')
SimObject('m5/objects/MemoryController.py')
SimObject('m5/objects/O3CPU.py')
SimObject('m5/objects/OzoneCPU.py')
SimObject('m5/objects/Pci.py')
SimObject('m5/objects/PhysicalMemory.py')
SimObject('m5/objects/Platform.py')
SimObject('m5/objects/Process.py')
SimObject('m5/objects/Repl.py')
SimObject('m5/objects/Root.py')
SimObject('m5/objects/Sampler.py')
SimObject('m5/objects/SimConsole.py')
SimObject('m5/objects/SimpleCPU.py')
SimObject('m5/objects/SimpleDisk.py')
#SimObject('m5/objects/SimpleOzoneCPU.py')
SimObject('m5/objects/SparcTLB.py')
SimObject('m5/objects/System.py')
SimObject('m5/objects/T1000.py')
#SimObject('m5/objects/Tru64System.py')
SimObject('m5/objects/Tsunami.py')
SimObject('m5/objects/Uart.py')

View file

@ -0,0 +1,35 @@
# 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: Nathan Binkert
import core
import debug
import event
import random
import sim_object
import stats
import trace

View file

@ -9,7 +9,7 @@ class BaseCache(MemObject):
"Use an adaptive compression scheme")
assoc = Param.Int("associativity")
block_size = Param.Int("block size in bytes")
latency = Param.Int("Latency")
latency = Param.Latency("Latency")
compressed_bus = Param.Bool(False,
"This cache connects to a compressed memory")
compression_latency = Param.Latency('0ns',
@ -59,6 +59,5 @@ class BaseCache(MemObject):
"Use the CPU ID to seperate calculations of prefetches")
prefetch_data_accesses_only = Param.Bool(False,
"Only prefetch on data not on instruction accesses")
hit_latency = Param.Int(1,"Hit Latency of the cache")
cpu_side = Port("Port on side closer to CPU")
mem_side = Port("Port on side closer to MEM")

View file

@ -5,7 +5,12 @@ class Bridge(MemObject):
type = 'Bridge'
side_a = Port('Side A port')
side_b = Port('Side B port')
queue_size_a = Param.Int(16, "The number of requests to buffer")
queue_size_b = Param.Int(16, "The number of requests to buffer")
req_size_a = Param.Int(16, "The number of requests to buffer")
req_size_b = Param.Int(16, "The number of requests to buffer")
resp_size_a = Param.Int(16, "The number of requests to buffer")
resp_size_b = Param.Int(16, "The number of requests to buffer")
delay = Param.Latency('0ns', "The latency of this bridge")
nack_delay = Param.Latency('0ns', "The latency of this bridge")
write_ack = Param.Bool(False, "Should this bridge ack writes")
fix_partial_write_a = Param.Bool(False, "Should this bridge fixup partial block writes")
fix_partial_write_b = Param.Bool(False, "Should this bridge fixup partial block writes")

View file

@ -11,6 +11,7 @@ class Bus(MemObject):
clock = Param.Clock("1GHz", "bus clock speed")
width = Param.Int(64, "bus width (bytes)")
responder_set = Param.Bool(False, "Did the user specify a default responder.")
block_size = Param.Int(64, "The default block size if one isn't set by a device attached to the bus.")
if build_env['FULL_SYSTEM']:
responder = BadAddr(pio_addr=0x0, pio_latency="1ps")
default = Port(Self.responder.pio, "Default port for requests that aren't handled by a device.")

View file

@ -19,6 +19,12 @@ class DmaDevice(PioDevice):
type = 'DmaDevice'
abstract = True
dma = Port(Self.pio.peerObj.port, "DMA port")
min_backoff_delay = Param.Latency('4ns',
"min time between a nack packet being received and the next request made by the device")
max_backoff_delay = Param.Latency('10us',
"max time between a nack packet being received and the next request made by the device")
class IsaFake(BasicPioDevice):
type = 'IsaFake'

View file

@ -51,6 +51,7 @@ import sys
import time
import convert
import proxy
import ticks
from util import *
@ -347,7 +348,7 @@ class UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True
class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100
class Float(ParamValue, float):
pass
cxx_type = 'double'
class MemorySize(CheckedInt):
cxx_type = 'uint64_t'
@ -477,12 +478,13 @@ def IncEthernetAddr(addr, val = 1):
assert(bytes[0] <= 255)
return ':'.join(map(lambda x: '%02x' % x, bytes))
class NextEthernetAddr(object):
addr = "00:90:00:00:00:01"
_NextEthernetAddr = "00:90:00:00:00:01"
def NextEthernetAddr():
global _NextEthernetAddr
def __init__(self, inc = 1):
self.value = NextEthernetAddr.addr
NextEthernetAddr.addr = IncEthernetAddr(NextEthernetAddr.addr, inc)
value = _NextEthernetAddr
_NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
return value
class EthernetAddr(ParamValue):
cxx_type = 'Net::EthAddr'
@ -508,17 +510,11 @@ class EthernetAddr(ParamValue):
def unproxy(self, base):
if self.value == NextEthernetAddr:
self.addr = self.value().value
return EthernetAddr(self.value())
return self
def __str__(self):
if self.value == NextEthernetAddr:
if hasattr(self, 'addr'):
return self.addr
else:
return "NextEthernetAddr (unresolved)"
else:
return self.value
def ini_str(self):
return self.value
time_formats = [ "%a %b %d %H:%M:%S %Z %Y",
"%a %b %d %H:%M:%S %Z %Y",
@ -1028,6 +1024,5 @@ __all__ = ['Param', 'VectorParam',
# see comment on imports at end of __init__.py.
from SimObject import isSimObject, isSimObjectSequence, isSimObjectClass
import proxy
import objects
import internal

View file

@ -210,7 +210,8 @@ class Event : public Serializable, public FastAlloc
void schedule(Tick t);
/// Reschedule the event with the current priority
void reschedule(Tick t);
// always parameter means to schedule if not already scheduled
void reschedule(Tick t, bool always = false);
/// Remove the event from the current schedule
void deschedule();
@ -402,16 +403,22 @@ Event::deschedule()
}
inline void
Event::reschedule(Tick t)
Event::reschedule(Tick t, bool always)
{
assert(scheduled());
clearFlags(Squashed);
assert(scheduled() || always);
#if TRACING_ON
when_scheduled = curTick;
#endif
_when = t;
queue->reschedule(this);
if (scheduled()) {
clearFlags(Squashed);
queue->reschedule(this);
} else {
setFlags(Scheduled);
queue->schedule(this);
}
}
inline void

View file

@ -61,21 +61,8 @@ void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
// We've accessed the next page of the stack, so extend the stack
// to cover it.
if(vaddr < p->stack_min && vaddr >= p->stack_min - TheISA::PageBytes)
{
p->stack_min -= TheISA::PageBytes;
if(p->stack_base - p->stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
p->pTable->allocate(p->stack_min, TheISA::PageBytes);
warn("Increasing stack size by one page.");
}
// Otherwise, we have an unexpected page fault. Report that fact,
// and what address was accessed to cause the fault.
else
{
if (!p->checkAndAllocNextPage(vaddr))
panic("Page table fault when accessing virtual address %#x\n", vaddr);
}
}
#endif

View file

@ -47,6 +47,7 @@
#include "mem/translating_port.hh"
#include "sim/builder.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/stats.hh"
#include "sim/syscall_emul.hh"
#include "sim/system.hh"
@ -182,7 +183,8 @@ Process::startup()
Port *mem_port;
mem_port = system->physmem->getPort("functional");
initVirtMem = new TranslatingPort("process init port", pTable, true);
initVirtMem = new TranslatingPort("process init port", this,
TranslatingPort::Always);
mem_port->setPeer(initVirtMem);
initVirtMem->setPeer(mem_port);
}
@ -250,6 +252,29 @@ Process::sim_fd(int tgt_fd)
return fd_map[tgt_fd];
}
bool
Process::checkAndAllocNextPage(Addr vaddr)
{
// if this is an initial write we might not have
if (vaddr >= stack_min && vaddr < stack_base) {
pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize);
return true;
}
// We've accessed the next page of the stack, so extend the stack
// to cover it.
if(vaddr < stack_min && vaddr >= stack_min - TheISA::PageBytes)
{
stack_min -= TheISA::PageBytes;
if(stack_base - stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
pTable->allocate(stack_min, TheISA::PageBytes);
warn("Increasing stack size by one page.");
return true;
}
return false;
}
void
Process::serialize(std::ostream &os)
{

View file

@ -45,7 +45,6 @@
#include <vector>
#include "base/statistics.hh"
#include "mem/translating_port.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
@ -60,28 +59,6 @@ namespace TheISA
class RemoteGDB;
}
//This needs to be templated for cases where 32 bit pointers are needed.
template<class AddrType>
void
copyStringArray(std::vector<std::string> &strings,
AddrType array_ptr, AddrType data_ptr,
TranslatingPort* memPort)
{
AddrType data_ptr_swap;
for (int i = 0; i < strings.size(); ++i) {
data_ptr_swap = htog(data_ptr);
memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
sizeof(AddrType));
memPort->writeString(data_ptr, strings[i].c_str());
array_ptr += sizeof(AddrType);
data_ptr += strings[i].size() + 1;
}
// add NULL terminator
data_ptr = 0;
memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
}
class Process : public SimObject
{
public:
@ -194,6 +171,10 @@ class Process : public SimObject
virtual void syscall(int64_t callnum, ThreadContext *tc) = 0;
// check if the this addr is on the next available page and allocate it
// if it's not we'll panic
bool checkAndAllocNextPage(Addr vaddr);
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};

75
src/sim/process_impl.hh Normal file
View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __SIM_PROCESS_IMPL_HH__
#define __SIM_PROCESS_IMPL_HH__
//
// The purpose of this code is to fake the loader & syscall mechanism
// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
// mode when we do have an OS.
//
#include "config/full_system.hh"
#if !FULL_SYSTEM
#include <string>
#include <vector>
#include "mem/translating_port.hh"
//This needs to be templated for cases where 32 bit pointers are needed.
template<class AddrType>
void
copyStringArray(std::vector<std::string> &strings,
AddrType array_ptr, AddrType data_ptr,
TranslatingPort* memPort)
{
AddrType data_ptr_swap;
for (int i = 0; i < strings.size(); ++i) {
data_ptr_swap = htog(data_ptr);
memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
sizeof(AddrType));
memPort->writeString(data_ptr, strings[i].c_str());
array_ptr += sizeof(AddrType);
data_ptr += strings[i].size() + 1;
}
// add NULL terminator
data_ptr = 0;
memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
}
#endif // !FULL_SYSTEM
#endif

View file

@ -87,10 +87,7 @@ namespace PseudoInst
Tick resume = curTick + Clock::Int::ns * ns;
if (quiesceEvent->scheduled())
quiesceEvent->reschedule(resume);
else
quiesceEvent->schedule(resume);
quiesceEvent->reschedule(resume, true);
DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
tc->getCpuPtr()->name(), ns, resume);
@ -110,10 +107,7 @@ namespace PseudoInst
Tick resume = curTick + tc->getCpuPtr()->cycles(cycles);
if (quiesceEvent->scheduled())
quiesceEvent->reschedule(resume);
else
quiesceEvent->schedule(resume);
quiesceEvent->reschedule(resume, true);
DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
tc->getCpuPtr()->name(), cycles, resume);

View file

@ -92,10 +92,9 @@ simulate(Tick num_cycles)
if (async_event) {
async_event = false;
if (async_statdump || async_statreset) {
Stats::StatEvent(async_statdump, async_statreset);
async_statdump = false;
async_statreset = false;
Stats::StatEvent(async_statdump, async_statreset);
}
if (async_exit) {

View file

@ -34,7 +34,7 @@ from m5.objects import *
# ====================
class L1(BaseCache):
latency = 1
latency = '1ns'
block_size = 64
mshrs = 12
tgts_per_mshr = 8
@ -46,7 +46,7 @@ class L1(BaseCache):
class L2(BaseCache):
block_size = 64
latency = 10
latency = '10ns'
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -35,7 +35,7 @@ m5.AddToPath('../configs/common')
# ====================
class L1(BaseCache):
latency = 1
latency = '1ns'
block_size = 64
mshrs = 4
tgts_per_mshr = 8
@ -47,7 +47,7 @@ class L1(BaseCache):
class L2(BaseCache):
block_size = 64
latency = 100
latency = '10ns'
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8
@ -73,6 +73,7 @@ for cpu in cpus:
L1(size = '32kB', assoc = 4))
# connect cpu level-1 caches to shared level-2 cache
cpu.connectMemPorts(system.toL2Bus)
cpu.clock = '2GHz'
# connect memory to membus
system.physmem.port = system.membus.port

View file

@ -33,13 +33,14 @@ m5.AddToPath('../configs/common')
class MyCache(BaseCache):
assoc = 2
block_size = 64
latency = 1
latency = '1ns'
mshrs = 10
tgts_per_mshr = 5
cpu = DerivO3CPU(cpu_id=0)
cpu.addTwoLevelCacheHierarchy(MyCache(size = '128kB'), MyCache(size = '256kB'),
MyCache(size = '2MB'))
cpu.clock = '2GHz'
system = System(cpu = cpu,
physmem = PhysicalMemory(),

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -34,7 +34,7 @@ from m5.objects import *
# ====================
class L1(BaseCache):
latency = 1
latency = '1ns'
block_size = 64
mshrs = 4
tgts_per_mshr = 8
@ -46,7 +46,7 @@ class L1(BaseCache):
class L2(BaseCache):
block_size = 64
latency = 100
latency = '10ns'
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8
@ -72,6 +72,7 @@ for cpu in cpus:
L1(size = '32kB', assoc = 4))
# connect cpu level-1 caches to shared level-2 cache
cpu.connectMemPorts(system.toL2Bus)
cpu.clock = '2GHz'
# connect memory to membus
system.physmem.port = system.membus.port

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -34,5 +34,6 @@ system = System(cpu = AtomicSimpleCPU(cpu_id=0),
membus = Bus())
system.physmem.port = system.membus.port
system.cpu.connectMemPorts(system.membus)
system.cpu.clock = '2GHz'
root = Root(system = system)

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -34,7 +34,7 @@ from m5.objects import *
# ====================
class L1(BaseCache):
latency = 1
latency = '1ns'
block_size = 64
mshrs = 4
tgts_per_mshr = 8
@ -46,7 +46,7 @@ class L1(BaseCache):
class L2(BaseCache):
block_size = 64
latency = 100
latency = '10ns'
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8
@ -72,6 +72,7 @@ for cpu in cpus:
L1(size = '32kB', assoc = 4))
# connect cpu level-1 caches to shared level-2 cache
cpu.connectMemPorts(system.toL2Bus)
cpu.clock = '2GHz'
# connect memory to membus
system.physmem.port = system.membus.port

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -32,17 +32,18 @@ from m5.objects import *
class MyCache(BaseCache):
assoc = 2
block_size = 64
latency = 1
latency = '1ns'
mshrs = 10
tgts_per_mshr = 5
cpu = TimingSimpleCPU(cpu_id=0)
cpu.addTwoLevelCacheHierarchy(MyCache(size = '128kB'), MyCache(size = '256kB'),
MyCache(size = '2MB'))
MyCache(size = '2MB', latency='10ns'))
system = System(cpu = cpu,
physmem = PhysicalMemory(),
membus = Bus())
system.physmem.port = system.membus.port
cpu.connectMemPorts(system.membus)
cpu.clock = '2GHz'
root = Root(system = system)

View file

@ -31,12 +31,49 @@ from m5.objects import *
m5.AddToPath('../configs/common')
import FSConfig
# --------------------
# Base L1 Cache
# ====================
class L1(BaseCache):
latency = '1ns'
block_size = 64
mshrs = 4
tgts_per_mshr = 8
protocol = CoherenceProtocol(protocol='moesi')
# ----------------------
# Base L2 Cache
# ----------------------
class L2(BaseCache):
block_size = 64
latency = '10ns'
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8
#cpu
cpus = [ AtomicSimpleCPU(cpu_id=i) for i in xrange(2) ]
#the system
system = FSConfig.makeLinuxAlphaSystem('atomic')
system.cpu = cpus
#create the l1/l2 bus
system.toL2Bus = Bus()
#connect up the l2 cache
system.l2c = L2(size='4MB', assoc=8)
system.l2c.cpu_side = system.toL2Bus.port
system.l2c.mem_side = system.membus.port
#connect up the cpu and l1s
for c in cpus:
c.connectMemPorts(system.membus)
c.addPrivateSplitL1Caches(L1(size = '32kB', assoc = 1),
L1(size = '32kB', assoc = 4))
# connect cpu level-1 caches to shared level-2 cache
c.connectMemPorts(system.toL2Bus)
c.clock = '2GHz'
root = Root(system=system)
m5.ticks.setGlobalFrequency('2GHz')
m5.ticks.setGlobalFrequency('1THz')

View file

@ -31,10 +31,49 @@ from m5.objects import *
m5.AddToPath('../configs/common')
import FSConfig
# --------------------
# Base L1 Cache
# ====================
class L1(BaseCache):
latency = '1ns'
block_size = 64
mshrs = 4
tgts_per_mshr = 8
protocol = CoherenceProtocol(protocol='moesi')
# ----------------------
# Base L2 Cache
# ----------------------
class L2(BaseCache):
block_size = 64
latency = '10ns'
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8
#cpu
cpu = AtomicSimpleCPU(cpu_id=0)
#the system
system = FSConfig.makeLinuxAlphaSystem('atomic')
system.cpu = cpu
cpu.connectMemPorts(system.membus)
#create the l1/l2 bus
system.toL2Bus = Bus()
#connect up the l2 cache
system.l2c = L2(size='4MB', assoc=8)
system.l2c.cpu_side = system.toL2Bus.port
system.l2c.mem_side = system.membus.port
#connect up the cpu and l1s
cpu.addPrivateSplitL1Caches(L1(size = '32kB', assoc = 1),
L1(size = '32kB', assoc = 4))
# connect cpu level-1 caches to shared level-2 cache
cpu.connectMemPorts(system.toL2Bus)
cpu.clock = '2GHz'
root = Root(system=system)
m5.ticks.setGlobalFrequency('2GHz')
m5.ticks.setGlobalFrequency('1THz')

View file

@ -31,11 +31,51 @@ from m5.objects import *
m5.AddToPath('../configs/common')
import FSConfig
# --------------------
# Base L1 Cache
# ====================
class L1(BaseCache):
latency = '1ns'
block_size = 64
mshrs = 4
tgts_per_mshr = 8
protocol = CoherenceProtocol(protocol='moesi')
# ----------------------
# Base L2 Cache
# ----------------------
class L2(BaseCache):
block_size = 64
latency = '10ns'
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8
#cpu
cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(2) ]
#the system
system = FSConfig.makeLinuxAlphaSystem('timing')
system.cpu = cpus
#create the l1/l2 bus
system.toL2Bus = Bus()
#connect up the l2 cache
system.l2c = L2(size='4MB', assoc=8)
system.l2c.cpu_side = system.toL2Bus.port
system.l2c.mem_side = system.membus.port
#connect up the cpu and l1s
for c in cpus:
c.connectMemPorts(system.membus)
c.addPrivateSplitL1Caches(L1(size = '32kB', assoc = 1),
L1(size = '32kB', assoc = 4))
# connect cpu level-1 caches to shared level-2 cache
c.connectMemPorts(system.toL2Bus)
c.clock = '2GHz'
root = Root(system=system)
m5.ticks.setGlobalFrequency('2GHz')
m5.ticks.setGlobalFrequency('1THz')

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