Ruby: Add support for functional accesses
authorBrad Beckmann ext:(%2C%20Nilay%20Vaish%20%3Cnilay%40cs.wisc.edu%3E) <Brad.Beckmann@amd.com>
Fri, 1 Jul 2011 00:49:26 +0000 (19:49 -0500)
committerBrad Beckmann ext:(%2C%20Nilay%20Vaish%20%3Cnilay%40cs.wisc.edu%3E) <Brad.Beckmann@amd.com>
Fri, 1 Jul 2011 00:49:26 +0000 (19:49 -0500)
This patch rpovides functional access support in Ruby. Currently only
the M5Port of RubyPort supports functional accesses. The support for
functional through the PioPort will be added as a separate patch.

60 files changed:
configs/example/ruby_direct_test.py
configs/example/ruby_fs.py
configs/example/ruby_mem_test.py
configs/example/ruby_network_test.py
configs/example/ruby_random_test.py
configs/example/se.py
configs/ruby/MESI_CMP_directory.py
configs/ruby/MI_example.py
configs/ruby/MOESI_CMP_directory.py
configs/ruby/MOESI_CMP_token.py
configs/ruby/MOESI_hammer.py
configs/ruby/Ruby.py
src/cpu/testers/memtest/MemTest.py
src/cpu/testers/memtest/memtest.cc
src/cpu/testers/memtest/memtest.hh
src/mem/packet.cc
src/mem/packet.hh
src/mem/protocol/MESI_CMP_directory-L1cache.sm
src/mem/protocol/MESI_CMP_directory-L2cache.sm
src/mem/protocol/MESI_CMP_directory-dir.sm
src/mem/protocol/MESI_CMP_directory-dma.sm
src/mem/protocol/MI_example-cache.sm
src/mem/protocol/MI_example-dir.sm
src/mem/protocol/MI_example-dma.sm
src/mem/protocol/MOESI_CMP_directory-L1cache.sm
src/mem/protocol/MOESI_CMP_directory-L2cache.sm
src/mem/protocol/MOESI_CMP_directory-dir.sm
src/mem/protocol/MOESI_CMP_directory-dma.sm
src/mem/protocol/MOESI_CMP_token-L1cache.sm
src/mem/protocol/MOESI_CMP_token-L2cache.sm
src/mem/protocol/MOESI_CMP_token-dir.sm
src/mem/protocol/MOESI_CMP_token-dma.sm
src/mem/protocol/MOESI_hammer-cache.sm
src/mem/protocol/MOESI_hammer-dir.sm
src/mem/protocol/MOESI_hammer-dma.sm
src/mem/protocol/RubySlicc_Exports.sm
src/mem/ruby/network/Network.cc
src/mem/ruby/network/Network.py
src/mem/ruby/profiler/Profiler.cc
src/mem/ruby/profiler/Profiler.py
src/mem/ruby/recorder/Tracer.cc
src/mem/ruby/recorder/Tracer.py
src/mem/ruby/slicc_interface/AbstractController.hh
src/mem/ruby/slicc_interface/Controller.py
src/mem/ruby/slicc_interface/SConscript
src/mem/ruby/system/Cache.py [deleted file]
src/mem/ruby/system/DirectoryMemory.cc
src/mem/ruby/system/DirectoryMemory.py [deleted file]
src/mem/ruby/system/RubyPort.cc
src/mem/ruby/system/RubyPort.hh
src/mem/ruby/system/RubySystem.py
src/mem/ruby/system/SConscript
src/mem/ruby/system/Sequencer.py
src/mem/ruby/system/System.cc
src/mem/ruby/system/System.hh
src/mem/slicc/ast/MemberExprAST.py
tests/configs/memtest-ruby.py
tests/configs/rubytest-ruby.py
tests/configs/simple-timing-mp-ruby.py
tests/configs/simple-timing-ruby.py

index 12585b8d5b5cda8b8c0876fdad548dbd16567076..55b1c85e6982b34b9e90a0437d09baf0b977e6e7 100644 (file)
@@ -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))
 
index 8c03e14cb0efdba9c4de6f73febcb60355efec19..ba4671d6e4fc81b0379e9a74c8e9adec47ab7ddf 100644 (file)
@@ -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)]
 
index 15416491926f7ff3a2ebb898dffbf56c7f6166bb..684aeffcc242c026edc2bf50a7417dd2799267b0 100644 (file)
@@ -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
index fb2a642b8250c1467328a3cc9277672880d9382f..d15206163bfc3526686671b3a13a8b5c287c0afd 100644 (file)
@@ -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:
index b60afc1923276fecc57164110a36dd3ea2822967..7655e32fdedaa7572dcc830045c7afc8eaa0ad6a 100644 (file)
@@ -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
 # -----------------------
index 9c35f80a0e56210962e8d36ba401c0d566952c82..be7d87bc68d609648c12ef1a330387eae99aad7a 100644 (file)
@@ -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
index f0e072f90e9d1fc39c7462c7d32790172effb3a8..fdb6ce0b0add1a4cbfc0212d38d92d23fcacf88c 100644 (file)
@@ -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)
index 5018f2c18a0371f8717ef51a59e4e3bfe14ecefc..4ea5e599344b6fcadc251f29a2e5d942d82d7c64 100644 (file)
@@ -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)
index c8b16fc5d1ab7c346160f7c4d74423027e7d5823..5da1cf310a2b089eb2c034c11c861f3b0fa22895 100644 (file)
@@ -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)
index 36999be5de9a32ada701cc539e8a71ddeefcd57d..c7f9dda11bc5eb91a19dbcd9c71142133b6e1c49 100644 (file)
@@ -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)
index 7e789d8e3f91309988e499776a2f032d0a357e63..6e46f3e0f0a1ec9215a1d7055392c697989ba078 100644 (file)
@@ -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
index 3c58dfd2fb4b6e77efe2068041eb94d99511b59a..9174709b48b677603f21f688c9cb72ca9fcabb4b 100644 (file)
@@ -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
index 957de8088ec4d6d5808f777307eff815899943b8..d5f456d69d2f4713b95eb19891c413d64c111c21 100644 (file)
@@ -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")
index d75bcb845b3238f08591e4edbf6302f1d4b55f5d..ef23825cd37a8b47996bebfa2996de5b71a0a43c 100644 (file)
@@ -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 {
index 4e489de5c69201e4fbb43977e21a2497e5e18502..292e7d83de8f26fb82434bee36d98b861df7822c 100644 (file)
@@ -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;
index 0296e7f0b7803835e90ba5977e84abd88e95bff8..5ec977ed4dc3c87b4f88d1dad33655cd9b7549a2 100644 (file)
@@ -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
index 5fcd9286ef661f2bbd00c8518ebc0bc93bb30bf1..be0c20d426f90a98612df71d6f9641e3ec9fbbe6 100644 (file)
@@ -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
index ebbd09ae09da80f87c5ed17adb73b1b88b06fd16..287bda004cfbb92f79b4eae46224bbe808b485e5 100644 (file)
@@ -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));
index 6044f5233c00a5bbfa48534cf74b527fcd34607f..a8fcb07d16494f835b0ab93e5a4298e9dd4f468b 100644 (file)
@@ -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));
index 6e3e796417ea5538ce14f337c40de86ce17de2b4..4232729054b9e39ee0a7894cbe05a6ae92ed4742 100644 (file)
@@ -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) {
index aee2e467d3f294958d6b2dd1197e074e2b08a63e..f32c73218fcf250a3c881896e3698a9723b86008 100644 (file)
@@ -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="...") {
index afc415b5a335faa795af9997a1e30f05289f2d6d..b11fddd95f19f96d02be361cc5d50447bcb65813 100644 (file)
@@ -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) {
       //
index baffe24120a060d02030af86ce6dff3b83bdebfb..2bd3afa44da0fda55e53f40d83fd23fd68789d19 100644 (file)
@@ -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);
index 8d79976fc10e8352a12053baaaf9cd951510508c..e13d247c799660e53cdf8cb51156d83a0fd4e04f 100644 (file)
@@ -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="...") {
index 35832ee9ca9cb419167f768fb3451150d11cf04d..2845d1ad1bf6ce8f103ed11143d621625aad70e1 100644 (file)
@@ -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;
index 8202a9c2f33c666cbd04ee53ee9e0f68fa410b9d..eb9693ed9ec808aa6033e48318db415030d0f1d6 100644 (file)
@@ -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);
index b13b56ffb3238337e7abc8ecae56cc6d3e872329..b71518b3f65a7c104d16a8551aceefd53b2bb344 100644 (file)
@@ -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)) {
index 0d99e354e415975b7580b15814af699ef16cce6d..e3aefbe514c43eec923590ccf75d3cfcf0eb7c2a 100644 (file)
@@ -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="...");
index d557132fc7bff3a1d80d8b69b61d6be526e00401..66789b594a6cb3d17efe24ea7c564a66fd4d1add 100644 (file)
@@ -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;
index c9c729263aed2b30f96cef9742fd01928463d302..078b5c7a6c4150f4c06e78d1aa23124eb2f52fb8 100644 (file)
@@ -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;
index 9ca0f1fc6a1e8bd7794a8a40166266568a8a42ad..9e6c6c99b739e3270eeb566bbe0272a1563322cd 100644 (file)
@@ -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) {
index 40b60490c923ddd2e9174a13409acc64e054d0d9..98666998a31b377b91a8e97715308813967be340 100644 (file)
@@ -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="...") {
index 6fe12d561dd33ae3d7d9d69de010142a5191c35c..edb1587e3750b9287c23cd53f13a72ed8a50d57b 100644 (file)
@@ -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;
index 828c762cba7394a30e502100dbe8a53acaf0dfff..bb0a97ac4a4c1903026890ec0ae35572438916e2 100644 (file)
@@ -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) {
index f254c1633dbe529d3bde2a44ad6585b8758c56fa..bfb3cb98df4a82ee71448d73d42083d7ffc0fa1b 100644 (file)
@@ -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="...") {
index ccd3aeb7f243ab99b9e9759af8c046f0f00ef61b..2e4a167840299f8379f85b5c74d1ed7f78960461 100644 (file)
@@ -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";
index caab897152e8439b00db3128b77ab69a147896ef..adb90eba99326575f075dbfa6ffb2dde49c1d101 100644 (file)
@@ -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
index 909f2f727acfb8a69c835f15ded3e1bae02ec3cb..9642b046e3b18f664f51bbab0eafd96bbb6be13a 100644 (file)
@@ -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("");
index afb77f09f866438a1be5c416aa0729004464e6fd..08a4439db0e758dea1462ec38e9d90f3f1a1ae19 100644 (file)
@@ -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()
index d15573aa4d5f812eb7583ad910b63d03616fcba6..3521911c2d21998ba7624badda399dd98c478c8d 100644 (file)
@@ -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("")
index bff59a83287b6976f14bf15299972bae471479b3..fcfe5338cf5df5e99713c9c1f3c8d649802dbfce 100644 (file)
@@ -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
index 7b6fd84210f8e48819530384db909c2f823f1f6a..7a689f9f73bd1db5c292e1caa776166ba8e98ace 100644 (file)
@@ -34,3 +34,4 @@ class RubyTracer(SimObject):
     type = 'RubyTracer'
     cxx_class = 'Tracer'
     warmup_length = Param.Int(100000, "")
+    ruby_system = Param.RubySystem("")
index eb8399af2152486fc3e7d5236f61ac0b8e9005f9..f1dac39ad2bfd14f3fb597d41e9ef763dd0e9f99 100644 (file)
@@ -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__
index a5ad45145ea5dc7fe596b3595d247eed55f9c04f..44e08ecdc12063563c9c693db89670cc4d50650b 100644 (file)
@@ -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("");
index 256f8e64ec87b7970811ce11131d7f9d92f57f64..9d4e6fe3bbfa9aa0eba438f8340aa74bea7a88be 100644 (file)
@@ -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 (file)
index ab3ec4b..0000000
+++ /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");
index fe54c8d7995c2cdcbd8d0f288536abd132387a19..c461ce09b71a11d85fdd87cb6638088570d924da 100644 (file)
@@ -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 (file)
index d3b6bc5..0000000
+++ /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")
index 40f8932571ebe72787e75391211955049eaab4ad..662f971f217678878ad03005a9a0027ae5895fe5 100644 (file)
@@ -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)
 {
index dc7a141c37bec6bcb0eb195a88d9ed620b70d926..e1ba2f7d1dbe17387cf7a6f593e4c3b834d8fa93 100644 (file)
@@ -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
index 7878cec639ce37bec793e030d4a7a27ed271f530..d66ada4b91f2c05522e6320f62af9dacac45240d 100644 (file)
@@ -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");
index f1e7c425c281179b11110829cc6173221e2a9402..0820ef2c8f84287af3bd5b4add0f3ec775fca383 100644 (file)
@@ -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')
index 16fb795f889a784e277f9fa989562e6d31dda9eb..5d56dc0006227b724e566b9802b4a386645efdc2 100644 (file)
@@ -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'
index d9c4fa821d3fc072b0ad61ebe0328a07b89f414a..81824b9b77ea38f59c84bf23188856a536d3a7a2 100644 (file)
@@ -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;
index 608aca1d8e7015c463ab6de84cd0de0c9450caa3..88a0186c5dfffe9f69332b27f0586f7e172fb4eb 100644 (file)
 #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__
-
-
-
index a13205252f72a32a86a3ad2c540c7552b63e54ae..412c178d8a174d1a6f4b04a7263c119c0239dfae 100644 (file)
@@ -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))
index 8e66c7334202dce42d1ce827abb21dbfb1a31b76..49f1520179e068897e7179da74a020b4c97e8118 100644 (file)
@@ -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
 # -----------------------
index 9c3207a90e346b2b0d9416efc58aacfb7b5810a6..b63833ccf6c6b15830613c59e7f81d7cf86c9302 100644 (file)
@@ -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
 # -----------------------
index 56b7ae1eb513914d0d08f96eb5edd122c653f77d..d57ccea150ca0f59a6696d1ade08658c8ede9792 100644 (file)
@@ -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))
 
index c07881d24de51f4c2c7e9fb90db3105f7a2bb3ff..1d67f6f976a6d4b9cc1780af7d114f59779280af 100644 (file)
@@ -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)