summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/example/ruby_direct_test.py2
-rw-r--r--configs/example/ruby_fs.py5
-rw-r--r--configs/example/ruby_mem_test.py24
-rw-r--r--configs/example/ruby_network_test.py2
-rw-r--r--configs/example/ruby_random_test.py8
-rw-r--r--configs/example/se.py2
-rw-r--r--configs/ruby/MESI_CMP_directory.py17
-rw-r--r--configs/ruby/MI_example.py11
-rw-r--r--configs/ruby/MOESI_CMP_directory.py19
-rw-r--r--configs/ruby/MOESI_CMP_token.py17
-rw-r--r--configs/ruby/MOESI_hammer.py13
-rw-r--r--configs/ruby/Ruby.py24
-rw-r--r--src/cpu/testers/memtest/MemTest.py2
-rw-r--r--src/cpu/testers/memtest/memtest.cc63
-rw-r--r--src/cpu/testers/memtest/memtest.hh2
-rw-r--r--src/mem/packet.cc6
-rw-r--r--src/mem/packet.hh19
-rw-r--r--src/mem/protocol/MESI_CMP_directory-L1cache.sm7
-rw-r--r--src/mem/protocol/MESI_CMP_directory-L2cache.sm9
-rw-r--r--src/mem/protocol/MESI_CMP_directory-dir.sm15
-rw-r--r--src/mem/protocol/MESI_CMP_directory-dma.sm4
-rw-r--r--src/mem/protocol/MI_example-cache.sm4
-rw-r--r--src/mem/protocol/MI_example-dir.sm10
-rw-r--r--src/mem/protocol/MI_example-dma.sm4
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-L1cache.sm7
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-L2cache.sm24
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-dir.sm18
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-dma.sm4
-rw-r--r--src/mem/protocol/MOESI_CMP_token-L1cache.sm4
-rw-r--r--src/mem/protocol/MOESI_CMP_token-L2cache.sm4
-rw-r--r--src/mem/protocol/MOESI_CMP_token-dir.sm14
-rw-r--r--src/mem/protocol/MOESI_CMP_token-dma.sm4
-rw-r--r--src/mem/protocol/MOESI_hammer-cache.sm4
-rw-r--r--src/mem/protocol/MOESI_hammer-dir.sm62
-rw-r--r--src/mem/protocol/MOESI_hammer-dma.sm4
-rw-r--r--src/mem/protocol/RubySlicc_Exports.sm7
-rw-r--r--src/mem/ruby/network/Network.cc1
-rw-r--r--src/mem/ruby/network/Network.py1
-rw-r--r--src/mem/ruby/profiler/Profiler.cc2
-rw-r--r--src/mem/ruby/profiler/Profiler.py1
-rw-r--r--src/mem/ruby/recorder/Tracer.cc2
-rw-r--r--src/mem/ruby/recorder/Tracer.py1
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh9
-rw-r--r--src/mem/ruby/slicc_interface/Controller.py1
-rw-r--r--src/mem/ruby/slicc_interface/SConscript1
-rw-r--r--src/mem/ruby/system/Cache.py41
-rw-r--r--src/mem/ruby/system/DirectoryMemory.cc4
-rw-r--r--src/mem/ruby/system/DirectoryMemory.py43
-rw-r--r--src/mem/ruby/system/RubyPort.cc175
-rw-r--r--src/mem/ruby/system/RubyPort.hh7
-rw-r--r--src/mem/ruby/system/RubySystem.py3
-rw-r--r--src/mem/ruby/system/SConscript3
-rw-r--r--src/mem/ruby/system/Sequencer.py1
-rw-r--r--src/mem/ruby/system/System.cc28
-rw-r--r--src/mem/ruby/system/System.hh13
-rw-r--r--src/mem/slicc/ast/MemberExprAST.py19
-rw-r--r--tests/configs/memtest-ruby.py12
-rw-r--r--tests/configs/rubytest-ruby.py8
-rw-r--r--tests/configs/simple-timing-mp-ruby.py2
-rw-r--r--tests/configs/simple-timing-ruby.py2
60 files changed, 576 insertions, 249 deletions
diff --git a/configs/example/ruby_direct_test.py b/configs/example/ruby_direct_test.py
index 12585b8d5..55b1c85e6 100644
--- a/configs/example/ruby_direct_test.py
+++ b/configs/example/ruby_direct_test.py
@@ -97,7 +97,7 @@ system.tester = RubyDirectedTester(requests_to_complete = \
options.requests,
generator = generator)
-system.ruby = Ruby.create_system(options, system)
+Ruby.create_system(options, system)
assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
diff --git a/configs/example/ruby_fs.py b/configs/example/ruby_fs.py
index 8c03e14cb..ba4671d6e 100644
--- a/configs/example/ruby_fs.py
+++ b/configs/example/ruby_fs.py
@@ -117,10 +117,7 @@ elif buildEnv['TARGET_ISA'] == "x86":
else:
fatal("incapable of building non-alpha or non-x86 full system!")
-system.ruby = Ruby.create_system(options,
- system,
- system.piobus,
- system._dma_devices)
+Ruby.create_system(options, system, system.piobus, system._dma_devices)
system.cpu = [CPUClass(cpu_id=i) for i in xrange(options.num_cpus)]
diff --git a/configs/example/ruby_mem_test.py b/configs/example/ruby_mem_test.py
index 154164919..684aeffcc 100644
--- a/configs/example/ruby_mem_test.py
+++ b/configs/example/ruby_mem_test.py
@@ -55,6 +55,10 @@ parser.add_option("--progress", type="int", default=1000,
help="Progress message interval "
"[default: %default]")
parser.add_option("--num-dmas", type="int", default=0, help="# of dma testers")
+parser.add_option("--functional", type="int", default=0,
+ help="percentage of accesses that should be functional")
+parser.add_option("--suppress-func-warnings", action="store_true",
+ help="suppress warnings when functional accesses fail")
#
# Add the ruby specific and protocol specific options
@@ -90,14 +94,15 @@ if options.num_cpus > block_size:
sys.exit(1)
#
-# Currently ruby does not support atomic, functional, or uncacheable accesses
+# Currently ruby does not support atomic or uncacheable accesses
#
cpus = [ MemTest(atomic = False, \
max_loads = options.maxloads, \
issue_dmas = False, \
- percent_functional = 0, \
+ percent_functional = options.functional, \
percent_uncacheable = 0, \
- progress_interval = options.progress) \
+ progress_interval = options.progress, \
+ suppress_func_warnings = options.suppress_func_warnings) \
for i in xrange(options.num_cpus) ]
system = System(cpu = cpus,
@@ -110,15 +115,14 @@ if options.num_dmas > 0:
issue_dmas = True, \
percent_functional = 0, \
percent_uncacheable = 0, \
- progress_interval = options.progress) \
+ progress_interval = options.progress, \
+ warn_on_failure = options.warn_on_failure) \
for i in xrange(options.num_dmas) ]
system.dma_devices = dmas
else:
dmas = []
-system.ruby = Ruby.create_system(options, \
- system, \
- dma_devices = dmas)
+Ruby.create_system(options, system, dma_devices = dmas)
#
# The tester is most effective when randomization is turned on and
@@ -141,6 +145,12 @@ for (i, cpu) in enumerate(cpus):
#
system.ruby._cpu_ruby_ports[i].deadlock_threshold = 5000000
+ #
+ # Ruby doesn't need the backing image of memory when running with
+ # the tester.
+ #
+ system.ruby._cpu_ruby_ports[i].access_phys_mem = False
+
for (i, dma) in enumerate(dmas):
#
# Tie the dma memtester ports to the correct functional port
diff --git a/configs/example/ruby_network_test.py b/configs/example/ruby_network_test.py
index fb2a642b8..d15206163 100644
--- a/configs/example/ruby_network_test.py
+++ b/configs/example/ruby_network_test.py
@@ -105,7 +105,7 @@ cpus = [ NetworkTest(fixed_pkts=options.fixed_pkts, \
system = System(cpu = cpus,
physmem = PhysicalMemory())
-system.ruby = Ruby.create_system(options, system)
+Ruby.create_system(options, system)
i = 0
for ruby_port in system.ruby._cpu_ruby_ports:
diff --git a/configs/example/ruby_random_test.py b/configs/example/ruby_random_test.py
index b60afc192..7655e32fd 100644
--- a/configs/example/ruby_random_test.py
+++ b/configs/example/ruby_random_test.py
@@ -99,7 +99,7 @@ tester = RubyTester(check_flush = check_flush,
#
system = System(tester = tester, physmem = PhysicalMemory())
-system.ruby = Ruby.create_system(options, system)
+Ruby.create_system(options, system)
assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
@@ -121,6 +121,12 @@ for ruby_port in system.ruby._cpu_ruby_ports:
#
ruby_port.using_ruby_tester = True
+ #
+ # Ruby doesn't need the backing image of memory when running with
+ # the tester.
+ #
+ ruby_port.access_phys_mem = False
+
# -----------------------
# run simulation
# -----------------------
diff --git a/configs/example/se.py b/configs/example/se.py
index 9c35f80a0..be7d87bc6 100644
--- a/configs/example/se.py
+++ b/configs/example/se.py
@@ -177,7 +177,7 @@ system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)],
if options.ruby:
options.use_map = True
- system.ruby = Ruby.create_system(options, system)
+ Ruby.create_system(options, system)
assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
else:
system.physmem.port = system.membus.port
diff --git a/configs/ruby/MESI_CMP_directory.py b/configs/ruby/MESI_CMP_directory.py
index f0e072f90..fdb6ce0b0 100644
--- a/configs/ruby/MESI_CMP_directory.py
+++ b/configs/ruby/MESI_CMP_directory.py
@@ -47,7 +47,7 @@ class L2Cache(RubyCache):
def define_options(parser):
return
-def create_system(options, system, piobus, dma_devices):
+def create_system(options, system, piobus, dma_devices, ruby_system):
if buildEnv['PROTOCOL'] != 'MESI_CMP_directory':
panic("This script requires the MESI_CMP_directory protocol to be built.")
@@ -88,13 +88,15 @@ def create_system(options, system, piobus, dma_devices):
cntrl_id = cntrl_count,
L1IcacheMemory = l1i_cache,
L1DcacheMemory = l1d_cache,
- l2_select_num_bits = l2_bits)
+ l2_select_num_bits = l2_bits,
+ ruby_system = ruby_system)
cpu_seq = RubySequencer(version = i,
icache = l1i_cache,
dcache = l1d_cache,
physMemPort = system.physmem.port,
- physmem = system.physmem)
+ physmem = system.physmem,
+ ruby_system = ruby_system)
l1_cntrl.sequencer = cpu_seq
@@ -123,7 +125,8 @@ def create_system(options, system, piobus, dma_devices):
l2_cntrl = L2Cache_Controller(version = i,
cntrl_id = cntrl_count,
- L2cacheMemory = l2_cache)
+ L2cacheMemory = l2_cache,
+ ruby_system = ruby_system)
exec("system.l2_cntrl%d = l2_cntrl" % i)
l2_cntrl_nodes.append(l2_cntrl)
@@ -148,9 +151,9 @@ def create_system(options, system, piobus, dma_devices):
cntrl_id = cntrl_count,
directory = \
RubyDirectoryMemory(version = i,
- size = \
- dir_size),
- memBuffer = mem_cntrl)
+ size = dir_size),
+ memBuffer = mem_cntrl,
+ ruby_system = ruby_system)
exec("system.dir_cntrl%d = dir_cntrl" % i)
dir_cntrl_nodes.append(dir_cntrl)
diff --git a/configs/ruby/MI_example.py b/configs/ruby/MI_example.py
index 5018f2c18..4ea5e5993 100644
--- a/configs/ruby/MI_example.py
+++ b/configs/ruby/MI_example.py
@@ -41,7 +41,7 @@ class Cache(RubyCache):
def define_options(parser):
return
-def create_system(options, system, piobus, dma_devices):
+def create_system(options, system, piobus, dma_devices, ruby_system):
if buildEnv['PROTOCOL'] != 'MI_example':
panic("This script requires the MI_example protocol to be built.")
@@ -80,13 +80,15 @@ def create_system(options, system, piobus, dma_devices):
#
l1_cntrl = L1Cache_Controller(version = i,
cntrl_id = cntrl_count,
- cacheMemory = cache)
+ cacheMemory = cache,
+ ruby_system = ruby_system)
cpu_seq = RubySequencer(version = i,
icache = cache,
dcache = cache,
physMemPort = system.physmem.port,
- physmem = system.physmem)
+ physmem = system.physmem,
+ ruby_system = ruby_system)
l1_cntrl.sequencer = cpu_seq
@@ -125,7 +127,8 @@ def create_system(options, system, piobus, dma_devices):
use_map = options.use_map,
map_levels = \
options.map_levels),
- memBuffer = mem_cntrl)
+ memBuffer = mem_cntrl,
+ ruby_system = ruby_system)
exec("system.dir_cntrl%d = dir_cntrl" % i)
dir_cntrl_nodes.append(dir_cntrl)
diff --git a/configs/ruby/MOESI_CMP_directory.py b/configs/ruby/MOESI_CMP_directory.py
index c8b16fc5d..5da1cf310 100644
--- a/configs/ruby/MOESI_CMP_directory.py
+++ b/configs/ruby/MOESI_CMP_directory.py
@@ -47,8 +47,8 @@ class L2Cache(RubyCache):
def define_options(parser):
return
-def create_system(options, system, piobus, dma_devices):
-
+def create_system(options, system, piobus, dma_devices, ruby_system):
+
if buildEnv['PROTOCOL'] != 'MOESI_CMP_directory':
panic("This script requires the MOESI_CMP_directory protocol to be built.")
@@ -88,13 +88,15 @@ def create_system(options, system, piobus, dma_devices):
cntrl_id = cntrl_count,
L1IcacheMemory = l1i_cache,
L1DcacheMemory = l1d_cache,
- l2_select_num_bits = l2_bits)
+ l2_select_num_bits = l2_bits,
+ ruby_system = ruby_system)
cpu_seq = RubySequencer(version = i,
icache = l1i_cache,
dcache = l1d_cache,
physMemPort = system.physmem.port,
- physmem = system.physmem)
+ physmem = system.physmem,
+ ruby_system = ruby_system)
l1_cntrl.sequencer = cpu_seq
@@ -122,7 +124,8 @@ def create_system(options, system, piobus, dma_devices):
l2_cntrl = L2Cache_Controller(version = i,
cntrl_id = cntrl_count,
- L2cacheMemory = l2_cache)
+ L2cacheMemory = l2_cache,
+ ruby_system = ruby_system)
exec("system.l2_cntrl%d = l2_cntrl" % i)
l2_cntrl_nodes.append(l2_cntrl)
@@ -147,9 +150,9 @@ def create_system(options, system, piobus, dma_devices):
cntrl_id = cntrl_count,
directory = \
RubyDirectoryMemory(version = i,
- size = \
- dir_size),
- memBuffer = mem_cntrl)
+ size = dir_size),
+ memBuffer = mem_cntrl,
+ ruby_system = ruby_system)
exec("system.dir_cntrl%d = dir_cntrl" % i)
dir_cntrl_nodes.append(dir_cntrl)
diff --git a/configs/ruby/MOESI_CMP_token.py b/configs/ruby/MOESI_CMP_token.py
index 36999be5d..c7f9dda11 100644
--- a/configs/ruby/MOESI_CMP_token.py
+++ b/configs/ruby/MOESI_CMP_token.py
@@ -54,7 +54,7 @@ def define_options(parser):
parser.add_option("--allow-atomic-migration", action="store_true",
help="allow migratory sharing for atomic only accessed blocks")
-def create_system(options, system, piobus, dma_devices):
+def create_system(options, system, piobus, dma_devices, ruby_system):
if buildEnv['PROTOCOL'] != 'MOESI_CMP_token':
panic("This script requires the MOESI_CMP_token protocol to be built.")
@@ -110,13 +110,15 @@ def create_system(options, system, piobus, dma_devices):
dynamic_timeout_enabled = \
not options.disable_dyn_timeouts,
no_mig_atomic = not \
- options.allow_atomic_migration)
+ options.allow_atomic_migration,
+ ruby_system = ruby_system)
cpu_seq = RubySequencer(version = i,
icache = l1i_cache,
dcache = l1d_cache,
physMemPort = system.physmem.port,
- physmem = system.physmem)
+ physmem = system.physmem,
+ ruby_system = ruby_system)
l1_cntrl.sequencer = cpu_seq
@@ -145,7 +147,8 @@ def create_system(options, system, piobus, dma_devices):
l2_cntrl = L2Cache_Controller(version = i,
cntrl_id = cntrl_count,
L2cacheMemory = l2_cache,
- N_tokens = n_tokens)
+ N_tokens = n_tokens,
+ ruby_system = ruby_system)
exec("system.l2_cntrl%d = l2_cntrl" % i)
l2_cntrl_nodes.append(l2_cntrl)
@@ -170,10 +173,10 @@ def create_system(options, system, piobus, dma_devices):
cntrl_id = cntrl_count,
directory = \
RubyDirectoryMemory(version = i,
- size = \
- dir_size),
+ size = dir_size),
memBuffer = mem_cntrl,
- l2_select_num_bits = l2_bits)
+ l2_select_num_bits = l2_bits,
+ ruby_system = ruby_system)
exec("system.dir_cntrl%d = dir_cntrl" % i)
dir_cntrl_nodes.append(dir_cntrl)
diff --git a/configs/ruby/MOESI_hammer.py b/configs/ruby/MOESI_hammer.py
index 7e789d8e3..6e46f3e0f 100644
--- a/configs/ruby/MOESI_hammer.py
+++ b/configs/ruby/MOESI_hammer.py
@@ -58,8 +58,8 @@ def define_options(parser):
parser.add_option("--dir-on", action="store_true",
help="Hammer: enable Full-bit Directory")
-def create_system(options, system, piobus, dma_devices):
-
+def create_system(options, system, piobus, dma_devices, ruby_system):
+
if buildEnv['PROTOCOL'] != 'MOESI_hammer':
panic("This script requires the MOESI_hammer protocol to be built.")
@@ -102,13 +102,15 @@ def create_system(options, system, piobus, dma_devices):
L1DcacheMemory = l1d_cache,
L2cacheMemory = l2_cache,
no_mig_atomic = not \
- options.allow_atomic_migration)
+ options.allow_atomic_migration,
+ ruby_system = ruby_system)
cpu_seq = RubySequencer(version = i,
icache = l1i_cache,
dcache = l1d_cache,
physMemPort = system.physmem.port,
- physmem = system.physmem)
+ physmem = system.physmem,
+ ruby_system = ruby_system)
l1_cntrl.sequencer = cpu_seq
@@ -181,7 +183,8 @@ def create_system(options, system, piobus, dma_devices):
probeFilter = pf,
memBuffer = mem_cntrl,
probe_filter_enabled = options.pf_on,
- full_bit_dir_enabled = options.dir_on)
+ full_bit_dir_enabled = options.dir_on,
+ ruby_system = ruby_system)
if options.recycle_latency:
dir_cntrl.recycle_latency = options.recycle_latency
diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py
index 3c58dfd2f..9174709b4 100644
--- a/configs/ruby/Ruby.py
+++ b/configs/ruby/Ruby.py
@@ -62,11 +62,15 @@ def define_options(parser):
def create_system(options, system, piobus = None, dma_devices = []):
+ system.ruby = RubySystem(clock = options.clock)
+ ruby = system.ruby
+
protocol = buildEnv['PROTOCOL']
exec "import %s" % protocol
try:
(cpu_sequencers, dir_cntrls, all_cntrls) = \
- eval("%s.create_system(options, system, piobus, dma_devices)" \
+ eval("%s.create_system(options, system, piobus, \
+ dma_devices, ruby)" \
% protocol)
except:
print "Error: could not create sytem for ruby protocol %s" % protocol
@@ -105,7 +109,7 @@ def create_system(options, system, piobus = None, dma_devices = []):
print "Error: could not create topology %s" % options.topology
raise
- network = NetworkClass(topology = net_topology)
+ network = NetworkClass(ruby_system = ruby, topology = net_topology)
#
# Loop through the directory controlers.
@@ -137,15 +141,13 @@ def create_system(options, system, piobus = None, dma_devices = []):
long(system.physmem.range.first) + 1
assert(total_mem_size.value == physmem_size)
- ruby_profiler = RubyProfiler(num_of_sequencers = len(cpu_sequencers))
+ ruby_profiler = RubyProfiler(ruby_system = ruby,
+ num_of_sequencers = len(cpu_sequencers))
+ ruby_tracer = RubyTracer(ruby_system = ruby)
- ruby = RubySystem(clock = options.clock,
- network = network,
- profiler = ruby_profiler,
- tracer = RubyTracer(),
- mem_size = total_mem_size)
-
+ ruby.network = network
+ ruby.profiler = ruby_profiler
+ ruby.tracer = ruby_tracer
+ ruby.mem_size = total_mem_size
ruby._cpu_ruby_ports = cpu_sequencers
ruby.random_seed = options.random_seed
-
- return ruby
diff --git a/src/cpu/testers/memtest/MemTest.py b/src/cpu/testers/memtest/MemTest.py
index 957de8088..d5f456d69 100644
--- a/src/cpu/testers/memtest/MemTest.py
+++ b/src/cpu/testers/memtest/MemTest.py
@@ -50,3 +50,5 @@ class MemTest(MemObject):
test = Port("Port to the memory system to test")
functional = Port("Port to the functional memory used for verification")
+ suppress_func_warnings = Param.Bool(False,
+ "suppress warnings when functional accesses fail.\n")
diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc
index d75bcb845..ef23825cd 100644
--- a/src/cpu/testers/memtest/memtest.cc
+++ b/src/cpu/testers/memtest/memtest.cc
@@ -146,7 +146,8 @@ MemTest::MemTest(const Params *p)
percentSourceUnaligned(p->percent_source_unaligned),
percentDestUnaligned(p->percent_dest_unaligned),
maxLoads(p->max_loads),
- atomic(p->atomic)
+ atomic(p->atomic),
+ suppress_func_warnings(p->suppress_func_warnings)
{
cachePort.snoopRangeSent = false;
funcPort.snoopRangeSent = true;
@@ -162,6 +163,7 @@ MemTest::MemTest(const Params *p)
// set up counters
noResponseCycles = 0;
numReads = 0;
+ numWrites = 0;
schedule(tickEvent, 0);
accessRetry = false;
@@ -201,9 +203,10 @@ MemTest::completeRequest(PacketPtr pkt)
dmaOutstanding = false;
}
- DPRINTF(MemTest, "completing %s at address %x (blk %x)\n",
+ DPRINTF(MemTest, "completing %s at address %x (blk %x) %s\n",
pkt->isWrite() ? "write" : "read",
- req->getPaddr(), blockAddr(req->getPaddr()));
+ req->getPaddr(), blockAddr(req->getPaddr()),
+ pkt->isError() ? "error" : "success");
MemTestSenderState *state =
dynamic_cast<MemTestSenderState *>(pkt->senderState);
@@ -217,28 +220,37 @@ MemTest::completeRequest(PacketPtr pkt)
assert(removeAddr != outstandingAddrs.end());
outstandingAddrs.erase(removeAddr);
- if (pkt->isRead()) {
- if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
- panic("%s: read of %x (blk %x) @ cycle %d "
- "returns %x, expected %x\n", name(),
- req->getPaddr(), blockAddr(req->getPaddr()), curTick(),
- *pkt_data, *data);
+ if (pkt->isError()) {
+ if (!suppress_func_warnings) {
+ warn("Functional Access failed for %x at %x\n",
+ pkt->isWrite() ? "write" : "read", req->getPaddr());
}
-
- numReads++;
- numReadsStat++;
-
- if (numReads == (uint64_t)nextProgressMessage) {
- ccprintf(cerr, "%s: completed %d read accesses @%d\n",
- name(), numReads, curTick());
- nextProgressMessage += progressInterval;
- }
-
- if (maxLoads != 0 && numReads >= maxLoads)
- exitSimLoop("maximum number of loads reached");
} else {
- assert(pkt->isWrite());
- numWritesStat++;
+ if (pkt->isRead()) {
+ if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
+ panic("%s: read of %x (blk %x) @ cycle %d "
+ "returns %x, expected %x\n", name(),
+ req->getPaddr(), blockAddr(req->getPaddr()), curTick(),
+ *pkt_data, *data);
+ }
+
+ numReads++;
+ numReadsStat++;
+
+ if (numReads == (uint64_t)nextProgressMessage) {
+ ccprintf(cerr, "%s: completed %d read, %d write accesses @%d\n",
+ name(), numReads, numWrites, curTick());
+ nextProgressMessage += progressInterval;
+ }
+
+ if (maxLoads != 0 && numReads >= maxLoads)
+ exitSimLoop("maximum number of loads reached");
+ } else {
+ assert(pkt->isWrite());
+ funcPort.writeBlob(req->getPaddr(), pkt_data, req->getSize());
+ numWrites++;
+ numWritesStat++;
+ }
}
noResponseCycles = 0;
@@ -361,6 +373,8 @@ MemTest::tick()
pkt->senderState = state;
if (do_functional) {
+ assert(pkt->needsResponse());
+ pkt->setSuppressFuncError();
cachePort.sendFunctional(pkt);
completeRequest(pkt);
} else {
@@ -392,9 +406,8 @@ MemTest::tick()
MemTestSenderState *state = new MemTestSenderState(result);
pkt->senderState = state;
- funcPort.writeBlob(req->getPaddr(), pkt_data, req->getSize());
-
if (do_functional) {
+ pkt->setSuppressFuncError();
cachePort.sendFunctional(pkt);
completeRequest(pkt);
} else {
diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh
index 4e489de5c..292e7d83d 100644
--- a/src/cpu/testers/memtest/memtest.hh
+++ b/src/cpu/testers/memtest/memtest.hh
@@ -174,9 +174,11 @@ class MemTest : public MemObject
Tick noResponseCycles;
uint64_t numReads;
+ uint64_t numWrites;
uint64_t maxLoads;
bool atomic;
+ bool suppress_func_warnings;
Stats::Scalar numReadsStat;
Stats::Scalar numWritesStat;
diff --git a/src/mem/packet.cc b/src/mem/packet.cc
index 0296e7f0b..5ec977ed4 100644
--- a/src/mem/packet.cc
+++ b/src/mem/packet.cc
@@ -148,10 +148,14 @@ MemCmd::commandInfo[] =
{ SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" },
/* BadAddressError -- memory address invalid */
{ SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" },
+ /* FunctionalReadError */
+ { SET3(IsRead, IsResponse, IsError), InvalidCmd, "FunctionalReadError" },
+ /* FunctionalWriteError */
+ { SET3(IsWrite, IsResponse, IsError), InvalidCmd, "FunctionalWriteError" },
/* PrintReq */
{ SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" },
/* Flush Request */
- { SET3(IsRequest, IsFlush, NeedsExclusive), InvalidCmd, "FlushReq" }
+ { SET3(IsRequest, IsFlush, NeedsExclusive), InvalidCmd, "FlushReq" },
};
bool
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index 5fcd9286e..be0c20d42 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -103,6 +103,8 @@ class MemCmd
NetworkNackError, // nacked at network layer (not by protocol)
InvalidDestError, // packet dest field invalid
BadAddressError, // memory address invalid
+ FunctionalReadError, // unable to fulfill functional read
+ FunctionalWriteError, // unable to fulfill functional write
// Fake simulator-only commands
PrintReq, // Print state matching address
FlushReq, //request for a cache flush
@@ -240,6 +242,9 @@ class Packet : public FastAlloc, public Printable
/// the data pointer points to an array (thus delete []) needs to
/// be called on it rather than simply delete.
static const FlagsType ARRAY_DATA = 0x00004000;
+ /// suppress the error if this packet encounters a functional
+ /// access failure.
+ static const FlagsType SUPPRESS_FUNC_ERROR = 0x00008000;
Flags flags;
@@ -428,6 +433,8 @@ class Packet : public FastAlloc, public Printable
void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); }
void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
bool isSupplyExclusive() { return flags.isSet(SUPPLY_EXCLUSIVE); }
+ void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
+ bool suppressFuncError() { return flags.isSet(SUPPRESS_FUNC_ERROR); }
// Network error conditions... encapsulate them as methods since
// their encoding keeps changing (from result field to command
@@ -617,6 +624,18 @@ class Packet : public FastAlloc, public Printable
makeResponse();
}
+ void
+ setFunctionalResponseStatus(bool success)
+ {
+ if (!success) {
+ if (isWrite()) {
+ cmd = MemCmd::FunctionalWriteError;
+ } else {
+ cmd = MemCmd::FunctionalReadError;
+ }
+ }
+ }
+
/**
* Take a request packet that has been returned as NACKED and
* modify it so that it can be sent out again. Only packets that
diff --git a/src/mem/protocol/MESI_CMP_directory-L1cache.sm b/src/mem/protocol/MESI_CMP_directory-L1cache.sm
index ebbd09ae0..287bda004 100644
--- a/src/mem/protocol/MESI_CMP_directory-L1cache.sm
+++ b/src/mem/protocol/MESI_CMP_directory-L1cache.sm
@@ -186,17 +186,24 @@ machine(L1Cache, "MSI Directory L1 Cache CMP")
AccessPermission getAccessPermission(Address addr) {
TBE tbe := L1_TBEs[addr];
if(is_valid(tbe)) {
+ DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(tbe.TBEState));
return L1Cache_State_to_permission(tbe.TBEState);
}
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
+ DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(cache_entry.CacheState));
return L1Cache_State_to_permission(cache_entry.CacheState);
}
+ DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent);
return AccessPermission:NotPresent;
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
void setAccessPermission(Entry cache_entry, Address addr, State state) {
if (is_valid(cache_entry)) {
cache_entry.changePermission(L1Cache_State_to_permission(state));
diff --git a/src/mem/protocol/MESI_CMP_directory-L2cache.sm b/src/mem/protocol/MESI_CMP_directory-L2cache.sm
index 6044f5233..a8fcb07d1 100644
--- a/src/mem/protocol/MESI_CMP_directory-L2cache.sm
+++ b/src/mem/protocol/MESI_CMP_directory-L2cache.sm
@@ -56,7 +56,7 @@ machine(L2Cache, "MESI Directory L2 Cache CMP")
NP, AccessPermission:Invalid, desc="Not present in either cache";
SS, AccessPermission:Read_Only, desc="L2 cache entry Shared, also present in one or more L1s";
M, AccessPermission:Read_Write, desc="L2 cache entry Modified, not present in any L1s", format="!b";
- MT, AccessPermission:Invalid, desc="L2 cache entry Modified in a local L1, assume L2 copy stale", format="!b";
+ MT, AccessPermission:Maybe_Stale, desc="L2 cache entry Modified in a local L1, assume L2 copy stale", format="!b";
// L2 replacement
M_I, AccessPermission:Busy, desc="L2 cache replacing, have all acks, sent dirty data to memory, waiting for ACK from memory";
@@ -217,17 +217,24 @@ machine(L2Cache, "MESI Directory L2 Cache CMP")
AccessPermission getAccessPermission(Address addr) {
TBE tbe := L2_TBEs[addr];
if(is_valid(tbe)) {
+ DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(tbe.TBEState));
return L2Cache_State_to_permission(tbe.TBEState);
}
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
+ DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(cache_entry.CacheState));
return L2Cache_State_to_permission(cache_entry.CacheState);
}
+ DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent);
return AccessPermission:NotPresent;
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
void setAccessPermission(Entry cache_entry, Address addr, State state) {
if (is_valid(cache_entry)) {
cache_entry.changePermission(L2Cache_State_to_permission(state));
diff --git a/src/mem/protocol/MESI_CMP_directory-dir.sm b/src/mem/protocol/MESI_CMP_directory-dir.sm
index 6e3e79641..423272905 100644
--- a/src/mem/protocol/MESI_CMP_directory-dir.sm
+++ b/src/mem/protocol/MESI_CMP_directory-dir.sm
@@ -55,7 +55,7 @@ machine(Directory, "MESI_CMP_filter_directory protocol")
ID, AccessPermission:Busy, desc="Intermediate state for DMA_READ when in I";
ID_W, AccessPermission:Busy, desc="Intermediate state for DMA_WRITE when in I";
- M, AccessPermission:Invalid, desc="memory copy may be stale, i.e. other modified copies may exist";
+ M, AccessPermission:Maybe_Stale, desc="memory copy may be stale, i.e. other modified copies may exist";
IM, AccessPermission:Busy, desc="Intermediate State I>M";
MI, AccessPermission:Busy, desc="Intermediate State M>I";
M_DRD, AccessPermission:Busy, desc="Intermediate State when there is a dma read";
@@ -147,10 +147,21 @@ machine(Directory, "MESI_CMP_filter_directory protocol")
AccessPermission getAccessPermission(Address addr) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
+ DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(tbe.TBEState));
return Directory_State_to_permission(tbe.TBEState);
}
- return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ if(directory.isPresent(addr)) {
+ DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState));
+ return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ }
+
+ DPRINTF(RubySlicc, "%s\n", AccessPermission:NotPresent);
+ return AccessPermission:NotPresent;
+ }
+
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getDirectoryEntry(addr).DataBlk;
}
void setAccessPermission(Address addr, State state) {
diff --git a/src/mem/protocol/MESI_CMP_directory-dma.sm b/src/mem/protocol/MESI_CMP_directory-dma.sm
index aee2e467d..f32c73218 100644
--- a/src/mem/protocol/MESI_CMP_directory-dma.sm
+++ b/src/mem/protocol/MESI_CMP_directory-dma.sm
@@ -42,6 +42,10 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ error("DMA does not support get data block.");
+ }
+
out_port(reqToDirectory_out, RequestMsg, reqToDirectory, desc="...");
in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
diff --git a/src/mem/protocol/MI_example-cache.sm b/src/mem/protocol/MI_example-cache.sm
index afc415b5a..b11fddd95 100644
--- a/src/mem/protocol/MI_example-cache.sm
+++ b/src/mem/protocol/MI_example-cache.sm
@@ -140,6 +140,10 @@ machine(L1Cache, "MI Example L1 Cache")
}
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
GenericMachineType getNondirectHitMachType(MachineID sender) {
if (machineIDToMachineType(sender) == MachineType:L1Cache) {
//
diff --git a/src/mem/protocol/MI_example-dir.sm b/src/mem/protocol/MI_example-dir.sm
index baffe2412..2bd3afa44 100644
--- a/src/mem/protocol/MI_example-dir.sm
+++ b/src/mem/protocol/MI_example-dir.sm
@@ -122,7 +122,11 @@ machine(Directory, "Directory protocol")
return Directory_State_to_permission(tbe.TBEState);
}
- return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ if(directory.isPresent(addr)) {
+ return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ }
+
+ return AccessPermission:NotPresent;
}
void setAccessPermission(Address addr, State state) {
@@ -131,6 +135,10 @@ machine(Directory, "Directory protocol")
}
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getDirectoryEntry(addr).DataBlk;
+ }
+
// ** OUT_PORTS **
out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
out_port(responseNetwork_out, ResponseMsg, responseFromDir);
diff --git a/src/mem/protocol/MI_example-dma.sm b/src/mem/protocol/MI_example-dma.sm
index 8d79976fc..e13d247c7 100644
--- a/src/mem/protocol/MI_example-dma.sm
+++ b/src/mem/protocol/MI_example-dma.sm
@@ -37,6 +37,10 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ error("DMA Controller does not support getDataBlock function.\n");
+ }
+
out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="...");
in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
diff --git a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm
index 35832ee9c..2845d1ad1 100644
--- a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm
@@ -197,14 +197,17 @@ machine(L1Cache, "Directory protocol")
AccessPermission getAccessPermission(Address addr) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
+ DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(tbe.TBEState));
return L1Cache_State_to_permission(tbe.TBEState);
}
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
+ DPRINTF(RubySlicc, "%s\n", L1Cache_State_to_permission(cache_entry.CacheState));
return L1Cache_State_to_permission(cache_entry.CacheState);
}
+ DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
return AccessPermission:NotPresent;
}
@@ -214,6 +217,10 @@ machine(L1Cache, "Directory protocol")
}
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
Event mandatory_request_type_to_event(RubyRequestType type) {
if (type == RubyRequestType:LD) {
return Event:Load;
diff --git a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
index 8202a9c2f..eb9693ed9 100644
--- a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
@@ -56,12 +56,12 @@ machine(L2Cache, "Token protocol")
// Stable states
NP, AccessPermission:Invalid, desc="Not Present";
I, AccessPermission:Invalid, desc="Invalid";
- ILS, AccessPermission:Busy, desc="Idle/NP, but local sharers exist";
- ILX, AccessPermission:Busy, desc="Idle/NP, but local exclusive exists";
- ILO, AccessPermission:Busy, desc="Idle/NP, but local owner exists";
- ILOX, AccessPermission:Busy, desc="Idle/NP, but local owner exists and chip is exclusive";
- ILOS, AccessPermission:Busy, desc="Idle/NP, but local owner exists and local sharers as well";
- ILOSX, AccessPermission:Busy, desc="Idle/NP, but local owner exists, local sharers exist, chip is exclusive ";
+ ILS, AccessPermission:Invalid, desc="Idle/NP, but local sharers exist";
+ ILX, AccessPermission:Invalid, desc="Idle/NP, but local exclusive exists";
+ ILO, AccessPermission:Invalid, desc="Idle/NP, but local owner exists";
+ ILOX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and chip is exclusive";
+ ILOS, AccessPermission:Invalid, desc="Idle/NP, but local owner exists and local sharers as well";
+ ILOSX, AccessPermission:Invalid, desc="Idle/NP, but local owner exists, local sharers exist, chip is exclusive ";
S, AccessPermission:Read_Only, desc="Shared, no local sharers";
O, AccessPermission:Read_Only, desc="Owned, no local sharers";
OLS, AccessPermission:Read_Only, desc="Owned with local sharers";
@@ -502,14 +502,22 @@ machine(L2Cache, "Token protocol")
AccessPermission getAccessPermission(Address addr) {
TBE tbe := TBEs[addr];
if(is_valid(tbe)) {
+ DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(tbe.TBEState));
return L2Cache_State_to_permission(tbe.TBEState);
}
Entry cache_entry := getCacheEntry(addr);
if(is_valid(cache_entry)) {
+ DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(cache_entry.CacheState));
return L2Cache_State_to_permission(cache_entry.CacheState);
}
+ else if (localDirectory.isTagPresent(addr)) {
+ DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(localDirectory[addr].DirState));
+ return L2Cache_State_to_permission(localDirectory[addr].DirState);
+ }
+
+ DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
return AccessPermission:NotPresent;
}
@@ -519,6 +527,10 @@ machine(L2Cache, "Token protocol")
}
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
MessageBuffer triggerQueue, ordered="true";
out_port(globalRequestNetwork_out, RequestMsg, GlobalRequestFromL2Cache);
diff --git a/src/mem/protocol/MOESI_CMP_directory-dir.sm b/src/mem/protocol/MOESI_CMP_directory-dir.sm
index b13b56ffb..b71518b3f 100644
--- a/src/mem/protocol/MOESI_CMP_directory-dir.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-dir.sm
@@ -50,16 +50,16 @@ machine(Directory, "Directory protocol")
// STATES
state_declaration(State, desc="Directory states", default="Directory_State_I") {
// Base states
- I, AccessPermission:Invalid, desc="Invalid";
+ I, AccessPermission:Read_Write, desc="Invalid";
S, AccessPermission:Read_Only, desc="Shared";
- O, AccessPermission:Read_Only, desc="Owner";
- M, AccessPermission:Read_Write, desc="Modified";
+ O, AccessPermission:Maybe_Stale, desc="Owner";
+ M, AccessPermission:Maybe_Stale, desc="Modified";
IS, AccessPermission:Busy, desc="Blocked, was in idle";
SS, AccessPermission:Read_Only, desc="Blocked, was in shared";
- OO, AccessPermission:Read_Only, desc="Blocked, was in owned";
- MO, AccessPermission:Read_Only, desc="Blocked, going to owner or maybe modified";
- MM, AccessPermission:Read_Only, desc="Blocked, going to modified";
+ OO, AccessPermission:Busy, desc="Blocked, was in owned";
+ MO, AccessPermission:Busy, desc="Blocked, going to owner or maybe modified";
+ MM, AccessPermission:Busy, desc="Blocked, going to modified";
MM_DMA, AccessPermission:Busy, desc="Blocked, going to I";
MI, AccessPermission:Busy, desc="Blocked on a writeback";
@@ -173,9 +173,11 @@ machine(Directory, "Directory protocol")
AccessPermission getAccessPermission(Address addr) {
if (directory.isPresent(addr)) {
+ DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState));
return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
}
+ DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
return AccessPermission:NotPresent;
}
@@ -185,6 +187,10 @@ machine(Directory, "Directory protocol")
}
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getDirectoryEntry(addr).DataBlk;
+ }
+
// if no sharers, then directory can be considered both a sharer and exclusive w.r.t. coherence checking
bool isBlockShared(Address addr) {
if (directory.isPresent(addr)) {
diff --git a/src/mem/protocol/MOESI_CMP_directory-dma.sm b/src/mem/protocol/MOESI_CMP_directory-dma.sm
index 0d99e354e..e3aefbe51 100644
--- a/src/mem/protocol/MOESI_CMP_directory-dma.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-dma.sm
@@ -68,6 +68,10 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ error("DMA Controller does not support getDataBlock().\n");
+ }
+
out_port(reqToDirectory_out, RequestMsg, reqToDir, desc="...");
out_port(respToDirectory_out, ResponseMsg, respToDir, desc="...");
out_port(foo1_out, ResponseMsg, foo1, desc="...");
diff --git a/src/mem/protocol/MOESI_CMP_token-L1cache.sm b/src/mem/protocol/MOESI_CMP_token-L1cache.sm
index d557132fc..66789b594 100644
--- a/src/mem/protocol/MOESI_CMP_token-L1cache.sm
+++ b/src/mem/protocol/MOESI_CMP_token-L1cache.sm
@@ -227,6 +227,10 @@ machine(L1Cache, "Token protocol")
return L1Icache_entry;
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
Entry getL1DCacheEntry(Address addr), return_by_pointer="yes" {
Entry L1Dcache_entry := static_cast(Entry, "pointer", L1DcacheMemory.lookup(addr));
return L1Dcache_entry;
diff --git a/src/mem/protocol/MOESI_CMP_token-L2cache.sm b/src/mem/protocol/MOESI_CMP_token-L2cache.sm
index c9c729263..078b5c7a6 100644
--- a/src/mem/protocol/MOESI_CMP_token-L2cache.sm
+++ b/src/mem/protocol/MOESI_CMP_token-L2cache.sm
@@ -156,6 +156,10 @@ machine(L2Cache, "Token protocol")
return cache_entry;
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
int getTokens(Entry cache_entry) {
if (is_valid(cache_entry)) {
return cache_entry.Tokens;
diff --git a/src/mem/protocol/MOESI_CMP_token-dir.sm b/src/mem/protocol/MOESI_CMP_token-dir.sm
index 9ca0f1fc6..9e6c6c99b 100644
--- a/src/mem/protocol/MOESI_CMP_token-dir.sm
+++ b/src/mem/protocol/MOESI_CMP_token-dir.sm
@@ -55,7 +55,7 @@ machine(Directory, "Token protocol")
state_declaration(State, desc="Directory states", default="Directory_State_O") {
// Base states
O, AccessPermission:Read_Only, desc="Owner, memory has valid data, but not necessarily all the tokens";
- NO, AccessPermission:Invalid, desc="Not Owner";
+ NO, AccessPermission:Maybe_Stale, desc="Not Owner";
L, AccessPermission:Busy, desc="Locked";
// Memory wait states - can block all messages including persistent requests
@@ -169,6 +169,10 @@ machine(Directory, "Token protocol")
return static_cast(Entry, directory[addr]);
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getDirectoryEntry(addr).DataBlk;
+ }
+
State getState(TBE tbe, Address addr) {
if (is_valid(tbe)) {
return tbe.TBEState;
@@ -206,7 +210,13 @@ machine(Directory, "Token protocol")
return Directory_State_to_permission(tbe.TBEState);
}
- return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ if (directory.isPresent(addr)) {
+ DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState));
+ return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ }
+
+ DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
+ return AccessPermission:NotPresent;
}
void setAccessPermission(Address addr, State state) {
diff --git a/src/mem/protocol/MOESI_CMP_token-dma.sm b/src/mem/protocol/MOESI_CMP_token-dma.sm
index 40b60490c..98666998a 100644
--- a/src/mem/protocol/MOESI_CMP_token-dma.sm
+++ b/src/mem/protocol/MOESI_CMP_token-dma.sm
@@ -70,6 +70,10 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ error("DMA Controller does not support getDataBlock function.\n");
+ }
+
out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="...");
in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
diff --git a/src/mem/protocol/MOESI_hammer-cache.sm b/src/mem/protocol/MOESI_hammer-cache.sm
index 6fe12d561..edb1587e3 100644
--- a/src/mem/protocol/MOESI_hammer-cache.sm
+++ b/src/mem/protocol/MOESI_hammer-cache.sm
@@ -189,6 +189,10 @@ machine(L1Cache, "AMD Hammer-like protocol")
return L1Icache_entry;
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getCacheEntry(addr).DataBlk;
+ }
+
Entry getL2CacheEntry(Address address), return_by_pointer="yes" {
Entry L2cache_entry := static_cast(Entry, "pointer", L2cacheMemory.lookup(address));
return L2cache_entry;
diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm
index 828c762cb..bb0a97ac4 100644
--- a/src/mem/protocol/MOESI_hammer-dir.sm
+++ b/src/mem/protocol/MOESI_hammer-dir.sm
@@ -59,38 +59,38 @@ machine(Directory, "AMD Hammer-like protocol")
// STATES
state_declaration(State, desc="Directory states", default="Directory_State_E") {
// Base states
- NX, AccessPermission:Invalid, desc="Not Owner, probe filter entry exists, block in O at Owner";
- NO, AccessPermission:Invalid, desc="Not Owner, probe filter entry exists, block in E/M at Owner";
+ NX, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in O at Owner";
+ NO, AccessPermission:Maybe_Stale, desc="Not Owner, probe filter entry exists, block in E/M at Owner";
S, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists pointing to the current owner";
O, AccessPermission:Read_Only, desc="Data clean, probe filter entry exists";
E, AccessPermission:Read_Write, desc="Exclusive Owner, no probe filter entry";
O_R, AccessPermission:Read_Only, desc="Was data Owner, replacing probe filter entry";
S_R, AccessPermission:Read_Only, desc="Was Not Owner or Sharer, replacing probe filter entry";
- NO_R, AccessPermission:Invalid, desc="Was Not Owner or Sharer, replacing probe filter entry";
-
- NO_B, AccessPermission:Invalid, "NO^B", desc="Not Owner, Blocked";
- NO_B_X, AccessPermission:Invalid, "NO^B", desc="Not Owner, Blocked, next queued request GETX";
- NO_B_S, AccessPermission:Invalid, "NO^B", desc="Not Owner, Blocked, next queued request GETS";
- NO_B_S_W, AccessPermission:Invalid, "NO^B", desc="Not Owner, Blocked, forwarded merged GETS, waiting for responses";
- O_B, AccessPermission:Invalid, "O^B", desc="Owner, Blocked";
- NO_B_W, AccessPermission:Invalid, desc="Not Owner, Blocked, waiting for Dram";
- O_B_W, AccessPermission:Invalid, desc="Owner, Blocked, waiting for Dram";
- NO_W, AccessPermission:Invalid, desc="Not Owner, waiting for Dram";
- O_W, AccessPermission:Invalid, desc="Owner, waiting for Dram";
- NO_DW_B_W, AccessPermission:Invalid, desc="Not Owner, Dma Write waiting for Dram and cache responses";
- NO_DR_B_W, AccessPermission:Invalid, desc="Not Owner, Dma Read waiting for Dram and cache responses";
- NO_DR_B_D, AccessPermission:Invalid, desc="Not Owner, Dma Read waiting for cache responses including dirty data";
- NO_DR_B, AccessPermission:Invalid, desc="Not Owner, Dma Read waiting for cache responses";
- NO_DW_W, AccessPermission:Invalid, desc="Not Owner, Dma Write waiting for Dram";
- O_DR_B_W, AccessPermission:Invalid, desc="Owner, Dma Read waiting for Dram and cache responses";
- O_DR_B, AccessPermission:Invalid, desc="Owner, Dma Read waiting for cache responses";
- WB, AccessPermission:Invalid, desc="Blocked on a writeback";
- WB_O_W, AccessPermission:Invalid, desc="Blocked on memory write, will go to O";
- WB_E_W, AccessPermission:Invalid, desc="Blocked on memory write, will go to E";
-
- NO_F, AccessPermission:Invalid, desc="Blocked on a flush";
- NO_F_W, AccessPermission:Invalid, desc="Not Owner, Blocked, waiting for Dram";
+ NO_R, AccessPermission:Busy, desc="Was Not Owner or Sharer, replacing probe filter entry";
+
+ NO_B, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked";
+ NO_B_X, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETX";
+ NO_B_S, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, next queued request GETS";
+ NO_B_S_W, AccessPermission:Busy, "NO^B", desc="Not Owner, Blocked, forwarded merged GETS, waiting for responses";
+ O_B, AccessPermission:Busy, "O^B", desc="Owner, Blocked";
+ NO_B_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
+ O_B_W, AccessPermission:Busy, desc="Owner, Blocked, waiting for Dram";
+ NO_W, AccessPermission:Busy, desc="Not Owner, waiting for Dram";
+ O_W, AccessPermission:Busy, desc="Owner, waiting for Dram";
+ NO_DW_B_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram and cache responses";
+ NO_DR_B_W, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for Dram and cache responses";
+ NO_DR_B_D, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses including dirty data";
+ NO_DR_B, AccessPermission:Busy, desc="Not Owner, Dma Read waiting for cache responses";
+ NO_DW_W, AccessPermission:Busy, desc="Not Owner, Dma Write waiting for Dram";
+ O_DR_B_W, AccessPermission:Busy, desc="Owner, Dma Read waiting for Dram and cache responses";
+ O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses";
+ WB, AccessPermission:Busy, desc="Blocked on a writeback";
+ WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O";
+ WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E";
+
+ NO_F, AccessPermission:Busy, desc="Blocked on a flush";
+ NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
}
// Events
@@ -190,6 +190,10 @@ machine(Directory, "AMD Hammer-like protocol")
return static_cast(Entry, directory[addr]);
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ return getDirectoryEntry(addr).DataBlk;
+ }
+
PfEntry getProbeFilterEntry(Address addr), return_by_pointer="yes" {
if (probe_filter_enabled || full_bit_dir_enabled) {
PfEntry pfEntry := static_cast(PfEntry, "pointer", probeFilter.lookup(addr));
@@ -239,7 +243,11 @@ machine(Directory, "AMD Hammer-like protocol")
return Directory_State_to_permission(tbe.TBEState);
}
- return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ if(directory.isPresent(addr)) {
+ return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState);
+ }
+
+ return AccessPermission:NotPresent;
}
void setAccessPermission(PfEntry pf_entry, Address addr, State state) {
diff --git a/src/mem/protocol/MOESI_hammer-dma.sm b/src/mem/protocol/MOESI_hammer-dma.sm
index f254c1633..bfb3cb98d 100644
--- a/src/mem/protocol/MOESI_hammer-dma.sm
+++ b/src/mem/protocol/MOESI_hammer-dma.sm
@@ -67,6 +67,10 @@ machine(DMA, "DMA Controller")
void setAccessPermission(Address addr, State state) {
}
+ DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ error("DMA Controller does not support getDataBlock function.\n");
+ }
+
out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="...");
in_port(dmaRequestQueue_in, SequencerMsg, mandatoryQueue, desc="...") {
diff --git a/src/mem/protocol/RubySlicc_Exports.sm b/src/mem/protocol/RubySlicc_Exports.sm
index ccd3aeb7f..2e4a16784 100644
--- a/src/mem/protocol/RubySlicc_Exports.sm
+++ b/src/mem/protocol/RubySlicc_Exports.sm
@@ -57,6 +57,13 @@ enumeration(AccessPermission, desc="...", default="AccessPermission_NotPresent")
Read_Only, desc="block is Read Only (modulo functional writes)";
Read_Write, desc="block is Read/Write";
+ // Possibly Invalid data
+ // The maybe stale permission indicates that accordingly to the protocol,
+ // there is no guarantee the block contains valid data. However, functional
+ // writes should update the block because a dataless PUT request may
+ // revalidate the block's data.
+ Maybe_Stale, desc="block can be stale or revalidated by a dataless PUT";
+
// Invalid data
Invalid, desc="block is in an Invalid base state";
NotPresent, desc="block is NotPresent";
diff --git a/src/mem/ruby/network/Network.cc b/src/mem/ruby/network/Network.cc
index caab89715..adb90eba9 100644
--- a/src/mem/ruby/network/Network.cc
+++ b/src/mem/ruby/network/Network.cc
@@ -48,6 +48,7 @@ Network::Network(const Params *p)
// Initialize the controller's network pointers
m_topology_ptr->initNetworkPtr(this);
+ p->ruby_system->registerNetwork(this);
}
void
diff --git a/src/mem/ruby/network/Network.py b/src/mem/ruby/network/Network.py
index 909f2f727..9642b046e 100644
--- a/src/mem/ruby/network/Network.py
+++ b/src/mem/ruby/network/Network.py
@@ -48,3 +48,4 @@ class RubyNetwork(SimObject):
number_of_virtual_networks = Param.Int(10, "");
topology = Param.Topology("");
control_msg_size = Param.Int(8, "");
+ ruby_system = Param.RubySystem("");
diff --git a/src/mem/ruby/profiler/Profiler.cc b/src/mem/ruby/profiler/Profiler.cc
index afb77f09f..08a4439db 100644
--- a/src/mem/ruby/profiler/Profiler.cc
+++ b/src/mem/ruby/profiler/Profiler.cc
@@ -92,6 +92,8 @@ Profiler::Profiler(const Params *p)
m_inst_profiler_ptr->setHotLines(m_hot_lines);
m_inst_profiler_ptr->setAllInstructions(m_all_instructions);
}
+
+ p->ruby_system->registerProfiler(this);
}
Profiler::~Profiler()
diff --git a/src/mem/ruby/profiler/Profiler.py b/src/mem/ruby/profiler/Profiler.py
index d15573aa4..3521911c2 100644
--- a/src/mem/ruby/profiler/Profiler.py
+++ b/src/mem/ruby/profiler/Profiler.py
@@ -36,3 +36,4 @@ class RubyProfiler(SimObject):
hot_lines = Param.Bool(False, "")
all_instructions = Param.Bool(False, "")
num_of_sequencers = Param.Int("")
+ ruby_system = Param.RubySystem("")
diff --git a/src/mem/ruby/recorder/Tracer.cc b/src/mem/ruby/recorder/Tracer.cc
index bff59a832..fcfe5338c 100644
--- a/src/mem/ruby/recorder/Tracer.cc
+++ b/src/mem/ruby/recorder/Tracer.cc
@@ -40,7 +40,7 @@ Tracer::Tracer(const Params *p)
m_enabled = false;
m_warmup_length = p->warmup_length;
assert(m_warmup_length > 0);
- RubySystem::m_tracer_ptr = this;
+ p->ruby_system->registerTracer(this);
}
void
diff --git a/src/mem/ruby/recorder/Tracer.py b/src/mem/ruby/recorder/Tracer.py
index 7b6fd8421..7a689f9f7 100644
--- a/src/mem/ruby/recorder/Tracer.py
+++ b/src/mem/ruby/recorder/Tracer.py
@@ -34,3 +34,4 @@ class RubyTracer(SimObject):
type = 'RubyTracer'
cxx_class = 'Tracer'
warmup_length = Param.Int(100000, "")
+ ruby_system = Param.RubySystem("")
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index eb8399af2..f1dac39ad 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -36,7 +36,9 @@
#include "mem/protocol/MachineType.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/DataBlock.hh"
#include "mem/ruby/network/Network.hh"
+#include "mem/ruby/system/System.hh"
#include "params/RubyController.hh"
#include "sim/sim_object.hh"
@@ -47,7 +49,7 @@ class AbstractController : public SimObject, public Consumer
{
public:
typedef RubyControllerParams Params;
- AbstractController(const Params *p) : SimObject(p) {}
+ AbstractController(const Params *p);
const Params *params() const { return (const Params *)_params; }
// returns the number of controllers created of the specific subtype
@@ -61,6 +63,8 @@ class AbstractController : public SimObject, public Consumer
virtual void blockOnQueue(Address, MessageBuffer*) = 0;
virtual void unblock(Address) = 0;
virtual void initNetworkPtr(Network* net_ptr) = 0;
+ virtual AccessPermission getAccessPermission(Address addr) = 0;
+ virtual DataBlock& getDataBlock(Address addr) = 0;
virtual void print(std::ostream & out) const = 0;
virtual void printStats(std::ostream & out) const = 0;
@@ -68,9 +72,6 @@ class AbstractController : public SimObject, public Consumer
virtual void wakeup() = 0;
// virtual void dumpStats(std::ostream & out) = 0;
virtual void clearStats() = 0;
-
- private:
- virtual AccessPermission getAccessPermission(Address addr) = 0;
};
#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
diff --git a/src/mem/ruby/slicc_interface/Controller.py b/src/mem/ruby/slicc_interface/Controller.py
index a5ad45145..44e08ecdc 100644
--- a/src/mem/ruby/slicc_interface/Controller.py
+++ b/src/mem/ruby/slicc_interface/Controller.py
@@ -41,3 +41,4 @@ class RubyController(SimObject):
buffer_size = Param.Int(0, "max buffer size 0 means infinite")
recycle_latency = Param.Int(10, "")
number_of_TBEs = Param.Int(256, "")
+ ruby_system = Param.RubySystem("");
diff --git a/src/mem/ruby/slicc_interface/SConscript b/src/mem/ruby/slicc_interface/SConscript
index 256f8e64e..9d4e6fe3b 100644
--- a/src/mem/ruby/slicc_interface/SConscript
+++ b/src/mem/ruby/slicc_interface/SConscript
@@ -35,6 +35,7 @@ if not env['RUBY']:
SimObject('Controller.py')
+Source('AbstractController.cc')
Source('AbstractEntry.cc')
Source('AbstractCacheEntry.cc')
Source('RubyRequest.cc')
diff --git a/src/mem/ruby/system/Cache.py b/src/mem/ruby/system/Cache.py
deleted file mode 100644
index ab3ec4b29..000000000
--- a/src/mem/ruby/system/Cache.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Steve Reinhardt
-# Brad Beckmann
-
-from m5.params import *
-from m5.SimObject import SimObject
-from Controller import RubyController
-
-class RubyCache(SimObject):
- type = 'RubyCache'
- cxx_class = 'CacheMemory'
- size = Param.MemorySize("capacity in bytes");
- latency = Param.Int("");
- assoc = Param.Int("");
- replacement_policy = Param.String("PSEUDO_LRU", "");
- start_index_bit = Param.Int(6, "index start, default 6 for 64-byte line");
diff --git a/src/mem/ruby/system/DirectoryMemory.cc b/src/mem/ruby/system/DirectoryMemory.cc
index fe54c8d79..c461ce09b 100644
--- a/src/mem/ruby/system/DirectoryMemory.cc
+++ b/src/mem/ruby/system/DirectoryMemory.cc
@@ -156,7 +156,7 @@ DirectoryMemory::lookup(PhysAddress address)
assert(isPresent(address));
Directory_Entry* entry;
uint64 idx;
- DPRINTF(RubyCache, "address: %s\n", address);
+ DPRINTF(RubyCache, "Looking up address: %s\n", address);
if (m_use_map) {
if (m_sparseMemory->exist(address)) {
@@ -166,6 +166,7 @@ DirectoryMemory::lookup(PhysAddress address)
// Note: SparseMemory internally creates a new Directory Entry
m_sparseMemory->add(address);
entry = m_sparseMemory->lookup(address);
+ entry->changePermission(AccessPermission_Read_Write);
}
} else {
idx = mapAddressToLocalIdx(address);
@@ -175,6 +176,7 @@ DirectoryMemory::lookup(PhysAddress address)
if (entry == NULL) {
entry = new Directory_Entry();
entry->getDataBlk().assign(m_ram->getBlockPtr(address));
+ entry->changePermission(AccessPermission_Read_Only);
m_entries[idx] = entry;
}
}
diff --git a/src/mem/ruby/system/DirectoryMemory.py b/src/mem/ruby/system/DirectoryMemory.py
deleted file mode 100644
index d3b6bc591..000000000
--- a/src/mem/ruby/system/DirectoryMemory.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Steve Reinhardt
-# Brad Beckmann
-
-from m5.params import *
-from m5.proxy import *
-from m5.SimObject import SimObject
-
-class RubyDirectoryMemory(SimObject):
- type = 'RubyDirectoryMemory'
- cxx_class = 'DirectoryMemory'
- version = Param.Int(0, "")
- size = Param.MemorySize("1GB", "capacity in bytes")
- use_map = Param.Bool(False, "enable sparse memory")
- map_levels = Param.Int(4, "sparse memory map levels")
- # the default value of the numa high bit is specified in the command line
- # option and must be passed into the directory memory sim object
- numa_high_bit = Param.Int("numa high bit")
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index 40f893257..662f971f2 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -31,8 +31,8 @@
#include "arch/x86/insts/microldstop.hh"
#endif // X86_ISA
#include "cpu/testers/rubytest/RubyTester.hh"
-#include "debug/MemoryAccess.hh"
#include "debug/Ruby.hh"
+#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/RubyPort.hh"
#include "mem/physical.hh"
@@ -54,6 +54,8 @@ RubyPort::RubyPort(const Params *p)
m_usingRubyTester = p->using_ruby_tester;
access_phys_mem = p->access_phys_mem;
+
+ ruby_system = p->ruby_system;
}
void
@@ -68,7 +70,7 @@ RubyPort::getPort(const std::string &if_name, int idx)
{
if (if_name == "port") {
return new M5Port(csprintf("%s-port%d", name(), idx), this,
- access_phys_mem);
+ ruby_system, access_phys_mem);
}
if (if_name == "pio_port") {
@@ -85,7 +87,7 @@ RubyPort::getPort(const std::string &if_name, int idx)
assert (physMemPort == NULL);
physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this,
- access_phys_mem);
+ ruby_system, access_phys_mem);
return physMemPort;
}
@@ -109,12 +111,13 @@ RubyPort::PioPort::PioPort(const std::string &_name,
ruby_port = _port;
}
-RubyPort::M5Port::M5Port(const std::string &_name,
- RubyPort *_port, bool _access_phys_mem)
+RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port,
+ RubySystem *_system, bool _access_phys_mem)
: SimpleTimingPort(_name, _port)
{
DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name);
ruby_port = _port;
+ ruby_system = _system;
_onRetryList = false;
access_phys_mem = _access_phys_mem;
}
@@ -289,6 +292,168 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
return false;
}
+bool
+RubyPort::M5Port::doFunctionalRead(PacketPtr pkt)
+{
+ Address address(pkt->getAddr());
+ Address line_address(address);
+ line_address.makeLineAddress();
+
+ AccessPermission accessPerm = AccessPermission_NotPresent;
+ int num_controllers = ruby_system->m_abs_cntrl_vec.size();
+
+ // In this loop, we try to figure which controller has a read only or
+ // a read write copy of the given address. Any valid copy would suffice
+ // for a functional read.
+
+ DPRINTF(RubyPort, "Functional Read request for %s\n",address);
+ for(int i = 0;i < num_controllers;++i)
+ {
+ accessPerm = ruby_system->m_abs_cntrl_vec[i]
+ ->getAccessPermission(line_address);
+ if(accessPerm == AccessPermission_Read_Only ||
+ accessPerm == AccessPermission_Read_Write)
+ {
+ unsigned startByte = address.getAddress() - line_address.getAddress();
+
+ uint8* data = pkt->getPtr<uint8_t>(true);
+ unsigned int size_in_bytes = pkt->getSize();
+ DataBlock& block = ruby_system->m_abs_cntrl_vec[i]
+ ->getDataBlock(line_address);
+
+ DPRINTF(RubyPort, "reading from %s block %s\n",
+ ruby_system->m_abs_cntrl_vec[i]->name(), block);
+ for (unsigned i = 0; i < size_in_bytes; ++i)
+ {
+ data[i] = block.getByte(i + startByte);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+RubyPort::M5Port::doFunctionalWrite(PacketPtr pkt)
+{
+ Address addr(pkt->getAddr());
+ Address line_addr = line_address(addr);
+ AccessPermission accessPerm = AccessPermission_NotPresent;
+ int num_controllers = ruby_system->m_abs_cntrl_vec.size();
+
+ DPRINTF(RubyPort, "Functional Write request for %s\n",addr);
+
+ unsigned int num_ro = 0;
+ unsigned int num_rw = 0;
+ unsigned int num_busy = 0;
+
+ // In this loop we count the number of controllers that have the given
+ // address in read only, read write and busy states.
+ for(int i = 0;i < num_controllers;++i)
+ {
+ accessPerm = ruby_system->m_abs_cntrl_vec[i]->
+ getAccessPermission(line_addr);
+ if(accessPerm == AccessPermission_Read_Only) num_ro++;
+ else if(accessPerm == AccessPermission_Read_Write) num_rw++;
+ else if(accessPerm == AccessPermission_Busy) num_busy++;
+ }
+
+ // If the number of read write copies is more than 1, then there is bug in
+ // coherence protocol. Otherwise, if all copies are in stable states, i.e.
+ // num_busy == 0, we update all the copies. If there is at least one copy
+ // in busy state, then we check if there is read write copy. If yes, then
+ // also we let the access go through.
+
+ DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n",
+ num_busy, num_ro, num_rw);
+ assert(num_rw <= 1);
+ if((num_busy == 0 && num_ro > 0) || num_rw == 1)
+ {
+ uint8* data = pkt->getPtr<uint8_t>(true);
+ unsigned int size_in_bytes = pkt->getSize();
+ unsigned startByte = addr.getAddress() - line_addr.getAddress();
+
+ for(int i = 0; i < num_controllers;++i)
+ {
+ accessPerm = ruby_system->m_abs_cntrl_vec[i]->
+ getAccessPermission(line_addr);
+ if(accessPerm == AccessPermission_Read_Only ||
+ accessPerm == AccessPermission_Read_Write||
+ accessPerm == AccessPermission_Maybe_Stale)
+ {
+ DataBlock& block = ruby_system->m_abs_cntrl_vec[i]
+ ->getDataBlock(line_addr);
+
+ DPRINTF(RubyPort, "%s\n",block);
+ for (unsigned i = 0; i < size_in_bytes; ++i)
+ {
+ block.setByte(i + startByte, data[i]);
+ }
+ DPRINTF(RubyPort, "%s\n",block);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void
+RubyPort::M5Port::recvFunctional(PacketPtr pkt)
+{
+ DPRINTF(RubyPort, "Functional access caught for address %#x\n",
+ pkt->getAddr());
+
+ // Check for pio requests and directly send them to the dedicated
+ // pio port.
+ if (!isPhysMemAddress(pkt->getAddr())) {
+ assert(ruby_port->pio_port != NULL);
+ DPRINTF(RubyPort, "Request for address 0x%#x is a pio request\n",
+ pkt->getAddr());
+ panic("RubyPort::PioPort::recvFunctional() not implemented!\n");
+ }
+
+ assert(pkt->getAddr() + pkt->getSize() <=
+ line_address(Address(pkt->getAddr())).getAddress() +
+ RubySystem::getBlockSizeBytes());
+
+ bool accessSucceeded = false;
+ bool needsResponse = pkt->needsResponse();
+
+ // Do the functional access on ruby memory
+ if (pkt->isRead()) {
+ accessSucceeded = doFunctionalRead(pkt);
+ } else if (pkt->isWrite()) {
+ accessSucceeded = doFunctionalWrite(pkt);
+ } else {
+ panic("RubyPort: unsupported functional command %s\n",
+ pkt->cmdString());
+ }
+
+ // Unless the requester explicitly said otherwise, generate an error if
+ // the functional request failed
+ if (!accessSucceeded && !pkt->suppressFuncError()) {
+ fatal("Ruby functional %s failed for address %#x\n",
+ pkt->isWrite() ? "write" : "read", pkt->getAddr());
+ }
+
+ if (access_phys_mem) {
+ // The attached physmem contains the official version of data.
+ // The following command performs the real functional access.
+ // This line should be removed once Ruby supplies the official version
+ // of data.
+ ruby_port->physMemPort->sendFunctional(pkt);
+ }
+
+ // turn packet around to go back to requester if response expected
+ if (needsResponse) {
+ pkt->setFunctionalResponseStatus(accessSucceeded);
+ DPRINTF(RubyPort, "Sending packet back over port\n");
+ sendFunctional(pkt);
+ }
+ DPRINTF(RubyPort, "Functional access %s!\n",
+ accessSucceeded ? "successful":"failed");
+}
+
void
RubyPort::ruby_hit_callback(PacketPtr pkt)
{
diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh
index dc7a141c3..e1ba2f7d1 100644
--- a/src/mem/ruby/system/RubyPort.hh
+++ b/src/mem/ruby/system/RubyPort.hh
@@ -50,12 +50,13 @@ class RubyPort : public MemObject
{
private:
RubyPort *ruby_port;
+ RubySystem* ruby_system;
bool _onRetryList;
bool access_phys_mem;
public:
M5Port(const std::string &_name, RubyPort *_port,
- bool _access_phys_mem);
+ RubySystem*_system, bool _access_phys_mem);
bool sendTiming(PacketPtr pkt);
void hitCallback(PacketPtr pkt);
unsigned deviceBlockSize() const;
@@ -69,9 +70,12 @@ class RubyPort : public MemObject
protected:
virtual bool recvTiming(PacketPtr pkt);
virtual Tick recvAtomic(PacketPtr pkt);
+ virtual void recvFunctional(PacketPtr pkt);
private:
bool isPhysMemAddress(Addr addr);
+ bool doFunctionalRead(PacketPtr pkt);
+ bool doFunctionalWrite(PacketPtr pkt);
};
friend class M5Port;
@@ -145,6 +149,7 @@ class RubyPort : public MemObject
M5Port* physMemPort;
PhysicalMemory* physmem;
+ RubySystem* ruby_system;
//
// Based on similar code in the M5 bus. Stores pointers to those ports
diff --git a/src/mem/ruby/system/RubySystem.py b/src/mem/ruby/system/RubySystem.py
index 7878cec63..d66ada4b9 100644
--- a/src/mem/ruby/system/RubySystem.py
+++ b/src/mem/ruby/system/RubySystem.py
@@ -39,9 +39,6 @@ class RubySystem(SimObject):
block_size_bytes = Param.Int(64,
"default cache block size; must be a power of two");
mem_size = Param.MemorySize("total memory size of the system");
- network = Param.RubyNetwork("")
- profiler = Param.RubyProfiler("");
- tracer = Param.RubyTracer("");
stats_filename = Param.String("ruby.stats",
"file to which ruby dumps its stats")
no_mem_vec = Param.Bool(False, "do not allocate Ruby's mem vector");
diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript
index f1e7c425c..0820ef2c8 100644
--- a/src/mem/ruby/system/SConscript
+++ b/src/mem/ruby/system/SConscript
@@ -33,9 +33,8 @@ Import('*')
if not env['RUBY']:
Return()
-SimObject('Cache.py')
+SimObject('AbstractMemory.py')
SimObject('Sequencer.py')
-SimObject('DirectoryMemory.py')
SimObject('MemoryControl.py')
SimObject('WireBuffer.py')
SimObject('RubySystem.py')
diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py
index 16fb795f8..5d56dc000 100644
--- a/src/mem/ruby/system/Sequencer.py
+++ b/src/mem/ruby/system/Sequencer.py
@@ -43,6 +43,7 @@ class RubyPort(MemObject):
using_network_tester = Param.Bool(False, "")
access_phys_mem = Param.Bool(True,
"should the rubyport atomically update phys_mem")
+ ruby_system = Param.RubySystem("")
class RubySequencer(RubyPort):
type = 'RubySequencer'
diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc
index d9c4fa821..81824b9b7 100644
--- a/src/mem/ruby/system/System.cc
+++ b/src/mem/ruby/system/System.cc
@@ -74,10 +74,6 @@ RubySystem::RubySystem(const Params *p)
m_memory_size_bits = floorLog2(m_memory_size_bytes);
}
- m_network_ptr = p->network;
- m_profiler_ptr = p->profiler;
- m_tracer_ptr = p->tracer;
-
g_eventQueue_ptr = new RubyEventQueue(p->eventq, m_clock);
g_system_ptr = this;
if (p->no_mem_vec) {
@@ -100,6 +96,30 @@ RubySystem::init()
m_profiler_ptr->clearStats();
}
+void
+RubySystem::registerNetwork(Network* network_ptr)
+{
+ m_network_ptr = network_ptr;
+}
+
+void
+RubySystem::registerProfiler(Profiler* profiler_ptr)
+{
+ m_profiler_ptr = profiler_ptr;
+}
+
+void
+RubySystem::registerTracer(Tracer* tracer_ptr)
+{
+ m_tracer_ptr = tracer_ptr;
+}
+
+void
+RubySystem::registerAbstractController(AbstractController* cntrl)
+{
+ m_abs_cntrl_vec.push_back(cntrl);
+}
+
RubySystem::~RubySystem()
{
delete m_network_ptr;
diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh
index 608aca1d8..88a0186c5 100644
--- a/src/mem/ruby/system/System.hh
+++ b/src/mem/ruby/system/System.hh
@@ -39,9 +39,12 @@
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/system/RubyPort.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "params/RubySystem.hh"
#include "sim/sim_object.hh"
+class AbstractController;
+class AbstractMemory;
class CacheRecorder;
class MemoryVector;
class Network;
@@ -128,6 +131,12 @@ class RubySystem : public SimObject
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ void registerNetwork(Network*);
+ void registerProfiler(Profiler*);
+ void registerTracer(Tracer*);
+ void registerAbstractMemory(AbstractMemory*);
+ void registerAbstractController(AbstractController*);
+
private:
// Private copy constructor and assignment operator
RubySystem(const RubySystem& obj);
@@ -153,6 +162,7 @@ class RubySystem : public SimObject
static Profiler* m_profiler_ptr;
static Tracer* m_tracer_ptr;
static MemoryVector* m_mem_vec_ptr;
+ std::vector<AbstractController*> m_abs_cntrl_vec;
};
inline std::ostream&
@@ -180,6 +190,3 @@ class RubyExitCallback : public Callback
};
#endif // __MEM_RUBY_SYSTEM_SYSTEM_HH__
-
-
-
diff --git a/src/mem/slicc/ast/MemberExprAST.py b/src/mem/slicc/ast/MemberExprAST.py
index a13205252..412c178d8 100644
--- a/src/mem/slicc/ast/MemberExprAST.py
+++ b/src/mem/slicc/ast/MemberExprAST.py
@@ -49,10 +49,15 @@ class MemberExprAST(ExprAST):
code.fix(fix)
# Verify that this is a valid field name for this type
- if self.field not in return_type.data_members:
- self.error("Invalid object field: " +
- "Type '%s' does not have data member %s" % \
- (return_type, self.field))
-
- # Return the type of the field
- return return_type.data_members[self.field].type
+ if self.field in return_type.data_members:
+ # Return the type of the field
+ return return_type.data_members[self.field].type
+ else:
+ if "interface" in return_type:
+ interface_type = self.symtab.find(return_type["interface"]);
+ if self.field in interface_type.data_members:
+ # Return the type of the field
+ return interface_type.data_members[self.field].type
+ self.error("Invalid object field: " +
+ "Type '%s' does not have data member %s" % \
+ (return_type, self.field))
diff --git a/tests/configs/memtest-ruby.py b/tests/configs/memtest-ruby.py
index 8e66c7334..49f152017 100644
--- a/tests/configs/memtest-ruby.py
+++ b/tests/configs/memtest-ruby.py
@@ -73,8 +73,8 @@ options.l3_assoc=2
nb_cores = 8
# ruby does not support atomic, functional, or uncacheable accesses
-cpus = [ MemTest(atomic=False, percent_functional=0, \
- percent_uncacheable=0) \
+cpus = [ MemTest(atomic=False, percent_functional=50,
+ percent_uncacheable=0, suppress_func_warnings=True) \
for i in xrange(nb_cores) ]
# overwrite options.num_cpus with the nb_cores value
@@ -85,7 +85,7 @@ system = System(cpu = cpus,
funcmem = PhysicalMemory(),
physmem = PhysicalMemory())
-system.ruby = Ruby.create_system(options, system)
+Ruby.create_system(options, system)
assert(len(cpus) == len(system.ruby._cpu_ruby_ports))
@@ -103,6 +103,12 @@ for (i, ruby_port) in enumerate(system.ruby._cpu_ruby_ports):
#
ruby_port.deadlock_threshold = 1000000
+ #
+ # Ruby doesn't need the backing image of memory when running with
+ # the tester.
+ #
+ ruby_port.access_phys_mem = False
+
# -----------------------
# run simulation
# -----------------------
diff --git a/tests/configs/rubytest-ruby.py b/tests/configs/rubytest-ruby.py
index 9c3207a90..b63833ccf 100644
--- a/tests/configs/rubytest-ruby.py
+++ b/tests/configs/rubytest-ruby.py
@@ -77,7 +77,7 @@ tester = RubyTester(checks_to_complete = 100, wakeup_frequency = 10)
system = System(tester = tester, physmem = PhysicalMemory())
-system.ruby = Ruby.create_system(options, system)
+Ruby.create_system(options, system)
assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
@@ -99,6 +99,12 @@ for ruby_port in system.ruby._cpu_ruby_ports:
#
ruby_port.using_ruby_tester = True
+ #
+ # Ruby doesn't need the backing image of memory when running with
+ # the tester.
+ #
+ ruby_port.access_phys_mem = False
+
# -----------------------
# run simulation
# -----------------------
diff --git a/tests/configs/simple-timing-mp-ruby.py b/tests/configs/simple-timing-mp-ruby.py
index 56b7ae1eb..d57ccea15 100644
--- a/tests/configs/simple-timing-mp-ruby.py
+++ b/tests/configs/simple-timing-mp-ruby.py
@@ -77,7 +77,7 @@ options.num_cpus = nb_cores
# system simulated
system = System(cpu = cpus, physmem = PhysicalMemory())
-system.ruby = Ruby.create_system(options, system)
+Ruby.create_system(options, system)
assert(options.num_cpus == len(system.ruby._cpu_ruby_ports))
diff --git a/tests/configs/simple-timing-ruby.py b/tests/configs/simple-timing-ruby.py
index c07881d24..1d67f6f97 100644
--- a/tests/configs/simple-timing-ruby.py
+++ b/tests/configs/simple-timing-ruby.py
@@ -74,7 +74,7 @@ options.num_cpus = 1
cpu = TimingSimpleCPU(cpu_id=0)
system = System(cpu = cpu, physmem = PhysicalMemory())
-system.ruby = Ruby.create_system(options, system)
+Ruby.create_system(options, system)
assert(len(system.ruby._cpu_ruby_ports) == 1)