MEM: Enable multiple distributed generalized memories
authorAndreas Hansson <andreas.hansson@arm.com>
Fri, 6 Apr 2012 17:46:31 +0000 (13:46 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Fri, 6 Apr 2012 17:46:31 +0000 (13:46 -0400)
This patch removes the assumption on having on single instance of
PhysicalMemory, and enables a distributed memory where the individual
memories in the system are each responsible for a single contiguous
address range.

All memories inherit from an AbstractMemory that encompasses the basic
behaviuor of a random access memory, and provides untimed access
methods. What was previously called PhysicalMemory is now
SimpleMemory, and a subclass of AbstractMemory. All future types of
memory controllers should inherit from AbstractMemory.

To enable e.g. the atomic CPU and RubyPort to access the now
distributed memory, the system has a wrapper class, called
PhysicalMemory that is aware of all the memories in the system and
their associated address ranges. This class thus acts as an
infinitely-fast bus and performs address decoding for these "shortcut"
accesses. Each memory can specify that it should not be part of the
global address map (used e.g. by the functional memories by some
testers). Moreover, each memory can be configured to be reported to
the OS configuration table, useful for populating ATAG structures, and
any potential ACPI tables.

Checkpointing support currently assumes that all memories have the
same size and organisation when creating and resuming from the
checkpoint. A future patch will enable a more flexible
re-organisation.

--HG--
rename : src/mem/PhysicalMemory.py => src/mem/AbstractMemory.py
rename : src/mem/PhysicalMemory.py => src/mem/SimpleMemory.py
rename : src/mem/physical.cc => src/mem/abstract_mem.cc
rename : src/mem/physical.hh => src/mem/abstract_mem.hh
rename : src/mem/physical.cc => src/mem/simple_mem.cc
rename : src/mem/physical.hh => src/mem/simple_mem.hh

65 files changed:
configs/common/FSConfig.py
configs/example/memtest.py
configs/example/ruby_direct_test.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/Network_test.py
configs/ruby/Ruby.py
configs/splash2/cluster.py
configs/splash2/run.py
src/arch/alpha/remote_gdb.cc
src/arch/alpha/remote_gdb.hh
src/arch/arm/ArmSystem.py
src/arch/arm/linux/system.cc
src/arch/arm/remote_gdb.hh
src/arch/arm/system.cc
src/arch/mips/remote_gdb.hh
src/arch/sparc/SparcSystem.py
src/arch/sparc/remote_gdb.hh
src/base/remote_gdb.cc
src/base/remote_gdb.hh
src/cpu/checker/thread_context.hh
src/cpu/inorder/thread_context.hh
src/cpu/o3/fetch_impl.hh
src/cpu/ozone/cpu.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/dev/alpha/backdoor.cc
src/dev/arm/RealView.py
src/dev/ide_disk.hh
src/mem/AbstractMemory.py [new file with mode: 0644]
src/mem/PhysicalMemory.py [deleted file]
src/mem/SConscript
src/mem/SimpleMemory.py [new file with mode: 0644]
src/mem/abstract_mem.cc [new file with mode: 0644]
src/mem/abstract_mem.hh [new file with mode: 0644]
src/mem/cache/mshr.cc
src/mem/physical.cc
src/mem/physical.hh
src/mem/ruby/system/RubyPort.cc
src/mem/simple_mem.cc [new file with mode: 0644]
src/mem/simple_mem.hh [new file with mode: 0644]
src/sim/System.py
src/sim/system.cc
src/sim/system.hh
tests/configs/inorder-timing.py
tests/configs/memtest-ruby.py
tests/configs/memtest.py
tests/configs/o3-timing-checker.py
tests/configs/o3-timing-mp.py
tests/configs/o3-timing.py
tests/configs/rubytest-ruby.py
tests/configs/simple-atomic-dummychecker.py
tests/configs/simple-atomic-mp.py
tests/configs/simple-atomic.py
tests/configs/simple-timing-mp-ruby.py
tests/configs/simple-timing-mp.py
tests/configs/simple-timing-ruby.py
tests/configs/simple-timing.py

index de2d9181df3aef63bc60d3749722074b9c540f8b..8e4be313748e2e3416d07afa4b72cb7de936589f 100644 (file)
@@ -73,7 +73,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
     # base address (including the PCI config space)
     self.bridge = Bridge(delay='50ns', nack_delay='4ns',
                          ranges = [AddrRange(IO_address_space_base, Addr.max)])
-    self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
+    self.physmem = SimpleMemory(range = AddrRange(mdesc.mem()))
     self.bridge.master = self.iobus.slave
     self.bridge.slave = self.membus.master
     self.physmem.port = self.membus.master
@@ -109,7 +109,7 @@ def makeLinuxAlphaRubySystem(mem_mode, mdesc = None):
         ide = IdeController(disks=[Parent.disk0, Parent.disk2],
                             pci_func=0, pci_dev=0, pci_bus=0)
         
-    physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
+    physmem = SimpleMemory(range = AddrRange(mdesc.mem()))
     self = LinuxAlphaSystem(physmem = physmem)
     if not mdesc:
         # generic system
@@ -178,8 +178,10 @@ def makeSparcSystem(mem_mode, mdesc = None):
     self.t1000 = T1000()
     self.t1000.attachOnChipIO(self.membus)
     self.t1000.attachIO(self.iobus)
-    self.physmem = PhysicalMemory(range = AddrRange(Addr('1MB'), size = '64MB'), zero = True)
-    self.physmem2 = PhysicalMemory(range = AddrRange(Addr('2GB'), size ='256MB'), zero = True)
+    self.physmem = SimpleMemory(range = AddrRange(Addr('1MB'), size = '64MB'),
+                                zero = True)
+    self.physmem2 = SimpleMemory(range = AddrRange(Addr('2GB'), size ='256MB'),
+                                 zero = True)
     self.bridge.master = self.iobus.slave
     self.bridge.slave = self.membus.master
     self.physmem.port = self.membus.master
@@ -269,8 +271,8 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, bare_metal=False):
     if bare_metal:
         # EOT character on UART will end the simulation
         self.realview.uart.end_on_eot = True
-        self.physmem = PhysicalMemory(range = AddrRange(Addr(mdesc.mem())),
-                                      zero = True)
+        self.physmem = SimpleMemory(range = AddrRange(Addr(mdesc.mem())),
+                                    zero = True)
     else:
         self.kernel = binary('vmlinux.arm.smp.fb.2.6.38.8')
         self.machine_type = machine_type
@@ -283,8 +285,10 @@ def makeArmSystem(mem_mode, machine_type, mdesc = None, bare_metal=False):
         boot_flags = 'earlyprintk console=ttyAMA0 lpj=19988480 norandmaps ' + \
                      'rw loglevel=8 mem=%s root=/dev/sda1' % mdesc.mem()
 
-        self.physmem = PhysicalMemory(range = AddrRange(self.realview.mem_start_addr,
-                                                        size = mdesc.mem()))
+        self.physmem = SimpleMemory(range =
+                                    AddrRange(self.realview.mem_start_addr,
+                                              size = mdesc.mem()),
+                                    conf_table_reported = True)
         self.realview.setupBootLoader(self.membus, self, binary)
         self.gic_cpu_addr = self.realview.gic.cpu_addr
         self.flags_addr = self.realview.realview_io.pio_addr + 0x30
@@ -319,7 +323,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None):
     self.iobus = Bus(bus_id=0)
     self.membus = MemBus(bus_id=1)
     self.bridge = Bridge(delay='50ns', nack_delay='4ns')
-    self.physmem = PhysicalMemory(range = AddrRange('1GB'))
+    self.physmem = SimpleMemory(range = AddrRange('1GB'))
     self.bridge.master = self.iobus.slave
     self.bridge.slave = self.membus.master
     self.physmem.port = self.membus.master
@@ -424,7 +428,7 @@ def makeX86System(mem_mode, numCPUs = 1, mdesc = None, self = None, Ruby = False
     self.mem_mode = mem_mode
 
     # Physical memory
-    self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
+    self.physmem = SimpleMemory(range = AddrRange(mdesc.mem()))
 
     # Platform
     self.pc = Pc()
index 5faee1bc701e121f0b65b1588bdc15481419132c..2dcccbba6841bba2fc777594f7f30483ca453da8 100644 (file)
@@ -140,8 +140,8 @@ for scale in treespec[:-2]:
      prototypes.insert(0, next)
 
 # system simulated
-system = System(funcmem = PhysicalMemory(),
-                physmem = PhysicalMemory(latency = "100ns"))
+system = System(funcmem = SimpleMemory(in_addr_map = False),
+                physmem = SimpleMemory(latency = "100ns"))
 
 def make_level(spec, prototypes, attach_obj, attach_port):
      fanout = spec[0]
index 53a1b68505c77880ea493175fbf56d8b290dd43e..f591d47ea543b539dd702bc9854f259ddbef8355 100644 (file)
@@ -83,11 +83,11 @@ else:
     sys.exit(1)
 
 #
-# Create the M5 system.  Note that the PhysicalMemory Object isn't
+# Create the M5 system.  Note that the Memory Object isn't
 # actually used by the rubytester, but is included to support the
 # M5 memory size == Ruby memory size checks
 #
-system = System(physmem = PhysicalMemory())
+system = System(physmem = SimpleMemory())
 
 #
 # Create the ruby random tester
index 4b0948365e95b226af7e4d448b1952a1d2f35474..4d7932b775fe126d4d2e6ba398d10843e21ddf62 100644 (file)
@@ -105,8 +105,8 @@ cpus = [ MemTest(atomic = False,
          for i in xrange(options.num_cpus) ]
 
 system = System(cpu = cpus,
-                funcmem = PhysicalMemory(),
-                physmem = PhysicalMemory())
+                funcmem = SimpleMemory(in_addr_map = False),
+                physmem = SimpleMemory())
 
 if options.num_dmas > 0:
     dmas = [ MemTest(atomic = False,
index 2d68a81ea8f934aaa677fb43c6840db4c0e110c0..1d44813acea3e2187ed92bf22f8eba500e6fac12 100644 (file)
@@ -103,7 +103,7 @@ cpus = [ NetworkTest(fixed_pkts=options.fixed_pkts,
 
 # create the desired simulated system
 system = System(cpu = cpus,
-                physmem = PhysicalMemory())
+                physmem = SimpleMemory())
 
 Ruby.create_system(options, system)
 
index 11571a29732df7867a86f1f541b1de8a87ad0aad..cb6a7477613f3865d02b09671a7fab594f5a87b3 100644 (file)
@@ -92,11 +92,11 @@ tester = RubyTester(check_flush = check_flush,
                     wakeup_frequency = options.wakeup_freq)
 
 #
-# Create the M5 system.  Note that the PhysicalMemory Object isn't
+# Create the M5 system.  Note that the Memory Object isn't
 # actually used by the rubytester, but is included to support the
 # M5 memory size == Ruby memory size checks
 #
-system = System(tester = tester, physmem = PhysicalMemory())
+system = System(tester = tester, physmem = SimpleMemory())
 
 Ruby.create_system(options, system)
 
index a2f8a09dca56a1cd6a5f20d41e9f0f9897b64c6c..853947475de93d6c949e1df04337f604f90159ee 100644 (file)
@@ -152,7 +152,7 @@ CPUClass.numThreads = numThreads;
 np = options.num_cpus
 
 system = System(cpu = [CPUClass(cpu_id=i) for i in xrange(np)],
-                physmem = PhysicalMemory(range=AddrRange("512MB")),
+                physmem = SimpleMemory(range=AddrRange("512MB")),
                 membus = Bus(), mem_mode = test_mem_mode)
 
 # Sanity check
index 4d490705bd16d6f5a7a6f44a406e075494f199bb..cd503ddc96807861285a48637d928e06bce399f8 100644 (file)
@@ -133,8 +133,9 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
         
         cntrl_count += 1
         
-    phys_mem_size = long(system.physmem.range.second) - \
-                      long(system.physmem.range.first) + 1
+    phys_mem_size = 0
+    for mem in system.memories.unproxy(system):
+        phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1
     mem_module_size = phys_mem_size / options.num_dirs
 
     for i in xrange(options.num_dirs):
index 1285c4b1da04e091703e3e1fbce17d7800f69023..de82c38f6cab92db3b777921470bf3d35e743cf3 100644 (file)
@@ -104,8 +104,9 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
 
         cntrl_count += 1
 
-    phys_mem_size = long(system.physmem.range.second) - \
-                      long(system.physmem.range.first) + 1
+    phys_mem_size = 0
+    for mem in system.memories.unproxy(system):
+        phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1
     mem_module_size = phys_mem_size / options.num_dirs
 
     for i in xrange(options.num_dirs):
index 5bc23ea72bf1964bd136d09f39211b4efc6ec085..10eeaf21a7b440110d7400f85595188540228c73 100644 (file)
@@ -132,8 +132,9 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
 
         cntrl_count += 1
         
-    phys_mem_size = long(system.physmem.range.second) - \
-                      long(system.physmem.range.first) + 1
+    phys_mem_size = 0
+    for mem in system.memories.unproxy(system):
+        phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1
     mem_module_size = phys_mem_size / options.num_dirs
 
     for i in xrange(options.num_dirs):
index f621df7674c4505d5840f601303fc6397cfeb203..4da7d7adf7aec7aff68cef8d4cfd8f4cbc8c270d 100644 (file)
@@ -155,8 +155,9 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
 
         cntrl_count += 1
         
-    phys_mem_size = long(system.physmem.range.second) - \
-                      long(system.physmem.range.first) + 1
+    phys_mem_size = 0
+    for mem in system.memories.unproxy(system):
+        phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1
     mem_module_size = phys_mem_size / options.num_dirs
 
     for i in xrange(options.num_dirs):
index 3f9d31482d0494410dbc5d1020c739ad6fce0132..622296289d73884304487ed05d01cb1e67c54fe3 100644 (file)
@@ -130,8 +130,9 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
 
         cntrl_count += 1
 
-    phys_mem_size = long(system.physmem.range.second) - \
-                      long(system.physmem.range.first) + 1
+    phys_mem_size = 0
+    for mem in system.memories.unproxy(system):
+        phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1
     mem_module_size = phys_mem_size / options.num_dirs
 
     #
index ff07c6b4d4ba23dbb9d1c8fe16d5c89ff9b516ef..b84fabde64c5980adef7e0b12919b0b901da9980 100644 (file)
@@ -105,8 +105,9 @@ def create_system(options, system, piobus, dma_ports, ruby_system):
 
         cntrl_count += 1
 
-    phys_mem_size = long(system.physmem.range.second) - \
-                      long(system.physmem.range.first) + 1
+    phys_mem_size = 0
+    for mem in system.memories.unproxy(system):
+        phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1
     mem_module_size = phys_mem_size / options.num_dirs
 
     for i in xrange(options.num_dirs):
index 1911a1eb7f33b4c84aeabd5bbbc4eb594dfadf66..046797a3ccca94afe5f2c91d424a8a484b7555b1 100644 (file)
@@ -172,9 +172,10 @@ def create_system(options, system, piobus = None, dma_ports = []):
         total_mem_size.value += dir_cntrl.directory.size.value
         dir_cntrl.directory.numa_high_bit = numa_bit
         
-    physmem_size = long(system.physmem.range.second) - \
-                     long(system.physmem.range.first) + 1
-    assert(total_mem_size.value == physmem_size)
+    phys_mem_size = 0
+    for mem in system.memories.unproxy(system):
+        phys_mem_size += long(mem.range.second) - long(mem.range.first) + 1
+    assert(total_mem_size.value == phys_mem_size)
 
     ruby_profiler = RubyProfiler(ruby_system = ruby,
                                  num_of_sequencers = len(cpu_sequencers))
index a6244a9ef3ee12d841618b85edc3868c7dce49b8..dd8ab784ac61f7856c583d4f5ce7caa0c4e98507 100644 (file)
@@ -211,8 +211,8 @@ else:
 # ----------------------
 # Create a system, and add system wide objects
 # ----------------------
-system = System(cpu = all_cpus, l1_ = all_l1s, l1bus_ = all_l1buses, physmem = PhysicalMemory(),
-                membus = Bus(clock = busFrequency))
+system = System(cpu = all_cpus, l1_ = all_l1s, l1bus_ = all_l1buses,
+                physmem = SimpleMemory(), membus = Bus(clock = busFrequency))
 
 system.toL2bus = Bus(clock = busFrequency)
 system.l2 = L2(size = options.l2size, assoc = 8)
index 2681a222d42109b5e6b0c1044de40b3ce7633feb..40dafceff2fad263938508ce7af69e71500e126a 100644 (file)
@@ -197,7 +197,7 @@ else:
 # ----------------------
 # Create a system, and add system wide objects
 # ----------------------
-system = System(cpu = cpus, physmem = PhysicalMemory(),
+system = System(cpu = cpus, physmem = SimpleMemory(),
                 membus = Bus(clock = busFrequency))
 
 system.toL2bus = Bus(clock = busFrequency)
index aa120686c8d656d2702e48921e24cded946e16ba..8e742c38b30cf8a954e3ae7a839a570d6892f06e 100644 (file)
@@ -166,7 +166,7 @@ RemoteGDB::acc(Addr va, size_t len)
 
     do  {
         if (IsK0Seg(va)) {
-            if (va < (K0SegBase + pmem->size())) {
+            if (va < (K0SegBase + system->memSize())) {
                 DPRINTF(GDBAcc, "acc:   Mapping is valid  K0SEG <= "
                         "%#x < K0SEG + size\n", va);
                 return true;
index 7223fea55ffb1bda93147691b3a149cf25f7168b..d9c124c7239842a6d4db6adf5ebaaf2e48ba767d 100644 (file)
@@ -42,7 +42,6 @@
 
 class System;
 class ThreadContext;
-class PhysicalMemory;
 
 namespace AlphaISA {
 
index e744c026c5428f49f4e61618c3e87a7181e7e19a..f4aedaf9800313300e93aabb660675339a83a3cc 100644 (file)
@@ -56,8 +56,6 @@ class ArmSystem(System):
     # 0x0 Revision
     midr_regval = Param.UInt32(0x350fc000, "MIDR value")
     boot_loader = Param.String("", "File that contains the boot loader code if any")
-    boot_loader_mem = Param.PhysicalMemory(NULL,
-                          "Memory object that boot loader is to be loaded into")
     gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface")
     flags_addr = Param.Addr(0, "Address of the flags register for MP booting")
 
@@ -67,5 +65,3 @@ class LinuxArmSystem(ArmSystem):
     machine_type = Param.ArmMachineType('RealView_PBX',
         "Machine id from http://www.arm.linux.org.uk/developer/machines/")
     atags_addr = Param.Addr(0x100, "Address where default atags structure should be written")
-
-
index 64bda4b4dc5b109068480b69237e0cae4cc1fc31..0d9e73a53a7fccd2d52e502db79693095a544859 100644 (file)
@@ -125,9 +125,14 @@ LinuxArmSystem::initState()
     ac->pagesize(8192);
     ac->rootdev(0);
 
+    AddrRangeList atagRanges = physmem.getConfAddrRanges();
+    if (atagRanges.size() != 1) {
+        fatal("Expected a single ATAG memory entry but got %d\n",
+              atagRanges.size());
+    }
     AtagMem *am = new AtagMem;
-    am->memSize(params()->physmem->size());
-    am->memStart(params()->physmem->start());
+    am->memSize(atagRanges.begin()->size());
+    am->memStart(atagRanges.begin()->start);
 
     AtagCmdline *ad = new AtagCmdline;
     ad->cmdline(params()->boot_osflags);
index 9ff93b8e62f11101cf862bb32240c77e170d2019..b75d921fb10902ea51d580ffdf8afdd5e3c8ab81 100644 (file)
@@ -37,7 +37,6 @@
 
 class System;
 class ThreadContext;
-class PhysicalMemory;
 
 namespace ArmISA
 {
index 7fbabafcb191c528af9d35b628f7bafdb7e54ae4..f6c4ad783447414beca104e6f27032fddecdec5e 100644 (file)
@@ -55,9 +55,6 @@ using namespace Linux;
 ArmSystem::ArmSystem(Params *p)
     : System(p), bootldr(NULL)
 {
-    if ((p->boot_loader == "") != (p->boot_loader_mem == NULL))
-        fatal("If boot_loader is specifed, memory to load it must be also.\n");
-
     if (p->boot_loader != "") {
         bootldr = createObjectFile(p->boot_loader);
 
index 18215ff8f84cc8c465a8e24d2c4facc949d96159..b9a2276079d1748de021c9f68cf0a22622cfb1f4 100644 (file)
@@ -37,7 +37,6 @@
 
 class System;
 class ThreadContext;
-class PhysicalMemory;
 
 namespace MipsISA
 {
index 92845235adcaa0a6f5ccc7b5a725ecb350078f58..b0fddf31170b2e5e213a78fb0732978009f414bf 100644 (file)
@@ -28,7 +28,7 @@
 
 from m5.params import *
 
-from PhysicalMemory import *
+from SimpleMemory import SimpleMemory
 from System import System
 
 class SparcSystem(System):
@@ -38,20 +38,20 @@ class SparcSystem(System):
     _hypervisor_desc_base = 0x1f12080000
     _partition_desc_base = 0x1f12000000
     # ROM for OBP/Reset/Hypervisor
-    rom = Param.PhysicalMemory(
-        PhysicalMemory(range=AddrRange(_rom_base, size='8MB')),
+    rom = Param.SimpleMemory(
+        SimpleMemory(range=AddrRange(_rom_base, size='8MB')),
             "Memory to hold the ROM data")
     # nvram
-    nvram = Param.PhysicalMemory(
-        PhysicalMemory(range=AddrRange(_nvram_base, size='8kB')),
+    nvram = Param.SimpleMemory(
+        SimpleMemory(range=AddrRange(_nvram_base, size='8kB')),
         "Memory to hold the nvram data")
     # hypervisor description
-    hypervisor_desc = Param.PhysicalMemory(
-        PhysicalMemory(range=AddrRange(_hypervisor_desc_base, size='8kB')),
+    hypervisor_desc = Param.SimpleMemory(
+        SimpleMemory(range=AddrRange(_hypervisor_desc_base, size='8kB')),
         "Memory to hold the hypervisor description")
     # partition description
-    partition_desc = Param.PhysicalMemory(
-        PhysicalMemory(range=AddrRange(_partition_desc_base, size='8kB')),
+    partition_desc = Param.SimpleMemory(
+        SimpleMemory(range=AddrRange(_partition_desc_base, size='8kB')),
         "Memory to hold the partition description")
 
     reset_addr = Param.Addr(_rom_base, "Address to load ROM at")
index 6ada8bdca5cdd326e340303a17052bb06f6f42e3..0176fd3232b4c796f4b5d313b1d89b83f711746b 100644 (file)
@@ -40,7 +40,6 @@
 
 class System;
 class ThreadContext;
-class PhysicalMemory;
 
 namespace SparcISA
 {
index 98e943084776730ecce40c4fe6bea7ec8642fb00..af6857a36ff72f01c85cff8d87b4ef42361da14c 100644 (file)
@@ -254,7 +254,7 @@ BaseRemoteGDB::Event::process(int revent)
 BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, size_t cacheSize)
     : event(NULL), listener(NULL), number(-1), fd(-1),
       active(false), attached(false),
-      system(_system), pmem(_system->physmem), context(c),
+      system(_system), context(c),
       gdbregs(cacheSize)
 {
     memset(gdbregs.regs, 0, gdbregs.bytes());
index 15a725438609ccbccbb251547cae9cf3473acb7c..babf610497b0773aa7bd8ab30547b662dbbef7d1 100644 (file)
@@ -42,7 +42,6 @@
 
 class System;
 class ThreadContext;
-class PhysicalMemory;
 
 class GDBListener;
 
@@ -131,7 +130,6 @@ class BaseRemoteGDB
     bool attached;
 
     System *system;
-    PhysicalMemory *pmem;
     ThreadContext *context;
 
   protected:
index 4aed0501c8e7cf0127613c576145f9e5d5a6a4eb..710d827cce037365fb2197dd1b5a6716a4b3f1ec 100644 (file)
@@ -121,8 +121,6 @@ class CheckerThreadContext : public ThreadContext
 
     System *getSystemPtr() { return actualTC->getSystemPtr(); }
 
-    PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); }
-
     TheISA::Kernel::Statistics *getKernelStats()
     { return actualTC->getKernelStats(); }
 
index aaf7d6ede1fa1ae543759c18d4e4f3836477bbe4..6f9bc5dac81b6286dadc0c40c8f38fa0dd8ed948 100644 (file)
@@ -114,10 +114,6 @@ class InOrderThreadContext : public ThreadContext
 
     void setNextMicroPC(uint64_t val) { };
 
-    /** Returns a pointer to physical memory. */
-    PhysicalMemory *getPhysMemPtr()
-    { assert(0); return 0; /*return cpu->physmem;*/ }
-
     /** Returns a pointer to this thread's kernel statistics. */
     TheISA::Kernel::Statistics *getKernelStats()
     { return thread->kernelStats; }
index df6ab26d5c4c09c11f3d62e84c82b769da339db5..0ff515855a045af86a83b5f8b678b05e4eecbfa4 100644 (file)
@@ -60,7 +60,6 @@
 #include "debug/Activity.hh"
 #include "debug/Fetch.hh"
 #include "mem/packet.hh"
-#include "mem/request.hh"
 #include "params/DerivO3CPU.hh"
 #include "sim/byteswap.hh"
 #include "sim/core.hh"
@@ -602,7 +601,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
         // Check that we're not going off into random memory
         // If we have, just wait around for commit to squash something and put
         // us on the right track
-        if (!cpu->system->isMemory(mem_req->getPaddr())) {
+        if (!cpu->system->isMemAddr(mem_req->getPaddr())) {
             warn("Address %#x is outside of physical memory, stopping fetch\n",
                     mem_req->getPaddr());
             fetchStatus[tid] = NoGoodAddr;
index 1bd2ee25b22661fd0dcc0fc38c83fb218686f3aa..91de37eff0e9be51787f754ad1cb2eb51bf0d338 100644 (file)
@@ -60,7 +60,6 @@ class Checkpoint;
 class EndQuiesceEvent;
 class MemoryController;
 class MemObject;
-class PhysicalMemory;
 class Process;
 class Request;
 
@@ -107,8 +106,6 @@ class OzoneCPU : public BaseCPU
 
         System *getSystemPtr() { return cpu->system; }
 
-        PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
-
         TheISA::Kernel::Statistics *getKernelStats()
         { return thread->getKernelStats(); }
 
@@ -314,7 +311,6 @@ class OzoneCPU : public BaseCPU
     TheISA::TLB *itb;
     TheISA::TLB *dtb;
     System *system;
-    PhysicalMemory *physmem;
 
     FrontEnd *frontEnd;
 
index 41bcf92685d04107d35efffe442c432a4b2413be..90f4fa579a0ea604e051acba241ca69b75df29e2 100644 (file)
@@ -95,10 +95,6 @@ AtomicSimpleCPU::init()
         }
     }
 
-    if (fastmem) {
-        AddrRangeList pmAddrList = system->physmem->getAddrRanges();
-        physMemAddr = *pmAddrList.begin();
-    }
     // Atomic doesn't do MT right now, so contextId == threadId
     ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT
     data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too
@@ -283,8 +279,8 @@ AtomicSimpleCPU::readMem(Addr addr, uint8_t * data,
             if (req->isMmappedIpr())
                 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
             else {
-                if (fastmem && pkt.getAddr() == physMemAddr)
-                    dcache_latency += system->physmem->doAtomicAccess(&pkt);
+                if (fastmem && system->isMemAddr(pkt.getAddr()))
+                    system->getPhysMem().access(&pkt);
                 else
                     dcache_latency += dcachePort.sendAtomic(&pkt);
             }
@@ -385,8 +381,8 @@ AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size,
                     dcache_latency +=
                         TheISA::handleIprWrite(thread->getTC(), &pkt);
                 } else {
-                    if (fastmem && pkt.getAddr() == physMemAddr)
-                        dcache_latency += system->physmem->doAtomicAccess(&pkt);
+                    if (fastmem && system->isMemAddr(pkt.getAddr()))
+                        system->getPhysMem().access(&pkt);
                     else
                         dcache_latency += dcachePort.sendAtomic(&pkt);
                 }
@@ -481,9 +477,8 @@ AtomicSimpleCPU::tick()
                                                Packet::Broadcast);
                     ifetch_pkt.dataStatic(&inst);
 
-                    if (fastmem && ifetch_pkt.getAddr() == physMemAddr)
-                        icache_latency =
-                            system->physmem->doAtomicAccess(&ifetch_pkt);
+                    if (fastmem && system->isMemAddr(ifetch_pkt.getAddr()))
+                        system->getPhysMem().access(&ifetch_pkt);
                     else
                         icache_latency = icachePort.sendAtomic(&ifetch_pkt);
 
index c0112836a39a0e5a80225d5e042cfbf451b89c22..3e6238f7decd4453666625696979de3886605caa 100644 (file)
@@ -110,8 +110,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     bool dcache_access;
     Tick dcache_latency;
 
-    Range<Addr> physMemAddr;
-
   protected:
 
     /** Return a reference to the data port. */
index 9727788012f636343fd67d199df4a8562c40fe96..a3579847bfe6d6c9a98b503fc334f6c47961f36a 100644 (file)
@@ -92,7 +92,7 @@ AlphaBackdoor::startup()
     alphaAccess->kernStart = system->getKernelStart();
     alphaAccess->kernEnd = system->getKernelEnd();
     alphaAccess->entryPoint = system->getKernelEntry();
-    alphaAccess->mem_size = system->physmem->size();
+    alphaAccess->mem_size = system->memSize();
     alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz
     Tsunami *tsunami = dynamic_cast<Tsunami *>(params()->platform);
     if (!tsunami)
index 4753bf5bfa3c949e0ddf09abd315affb135cad77..973a2cd52c2ed4756e52ce8d93307213571c0e25 100644 (file)
@@ -49,7 +49,7 @@ from Ide import *
 from Platform import Platform
 from Terminal import Terminal
 from Uart import Uart
-from PhysicalMemory import *
+from SimpleMemory import SimpleMemory
 
 class AmbaDevice(BasicPioDevice):
     type = 'AmbaDevice'
@@ -146,10 +146,11 @@ class RealView(Platform):
     max_mem_size = Param.Addr('256MB', "Maximum amount of RAM supported by platform")
 
     def setupBootLoader(self, mem_bus, cur_sys, loc):
-        self.nvmem = PhysicalMemory(range = AddrRange(Addr('2GB'), size = '64MB'), zero = True)
+        self.nvmem = SimpleMemory(range = AddrRange(Addr('2GB'),
+                                                    size = '64MB'),
+                                  zero = True)
         self.nvmem.port = mem_bus.master
         cur_sys.boot_loader = loc('boot.arm')
-        cur_sys.boot_loader_mem = self.nvmem
 
 
 # Reference for memory map and interrupt number
@@ -438,7 +439,8 @@ class VExpress_EMM(RealView):
                             BAR0 = 0x1C1A0000, BAR0Size = '256B',
                             BAR1 = 0x1C1A0100, BAR1Size = '4096B',
                             BAR0LegacyIO = True, BAR1LegacyIO = True)
-    vram           = PhysicalMemory(range = AddrRange(0x18000000, size='32MB'), zero = True)
+    vram           = SimpleMemory(range = AddrRange(0x18000000, size='32MB'),
+                                  zero = True)
     rtc            = PL031(pio_addr=0x1C170000, int_num=36)
 
     l2x0_fake      = IsaFake(pio_addr=0x2C100000, pio_size=0xfff)
@@ -453,10 +455,10 @@ class VExpress_EMM(RealView):
     mmc_fake       = AmbaFake(pio_addr=0x1c050000)
 
     def setupBootLoader(self, mem_bus, cur_sys, loc):
-        self.nvmem = PhysicalMemory(range = AddrRange(0, size = '64MB'), zero = True)
+        self.nvmem = SimpleMemory(range = AddrRange(0, size = '64MB'),
+                                  zero = True)
         self.nvmem.port = mem_bus.master
         cur_sys.boot_loader = loc('boot_emm.arm')
-        cur_sys.boot_loader_mem = self.nvmem
         cur_sys.atags_addr = 0x80000100
 
     # Attach I/O devices that are on chip and also set the appropriate
index af42bd2c9aff769eafb37adb5d06e801217df86f..b29d13870ef5d5e43ea1161132fb0259c5e79937 100644 (file)
@@ -186,7 +186,6 @@ typedef enum DmaState {
     Dma_Transfer
 } DmaState_t;
 
-class PhysicalMemory;
 class IdeController;
 
 /**
diff --git a/src/mem/AbstractMemory.py b/src/mem/AbstractMemory.py
new file mode 100644 (file)
index 0000000..bf1621f
--- /dev/null
@@ -0,0 +1,61 @@
+# Copyright (c) 2012 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# Copyright (c) 2005-2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+#          Andreas Hansson
+
+from m5.params import *
+from MemObject import MemObject
+
+class AbstractMemory(MemObject):
+    type = 'AbstractMemory'
+    abstract = True
+    range = Param.AddrRange(AddrRange('128MB'), "Address range")
+    file = Param.String('', "Memory-mapped file")
+    null = Param.Bool(False, "Do not store data, always return zero")
+    zero = Param.Bool(False, "Initialize memory with zeros")
+
+    # All memories are passed to the global physical memory, and
+    # certain memories may be excluded from the global address map,
+    # e.g. by the testers that use shadow memories as a reference
+    in_addr_map = Param.Bool(True, "Memory part of the global address map")
+
+    # Should the bootloader include this memory when passing
+    # configuration information about the physical memory layout to
+    # the kernel, e.g. using ATAG or ACPI
+    conf_table_reported = Param.Bool(False, "Report to configuration table")
diff --git a/src/mem/PhysicalMemory.py b/src/mem/PhysicalMemory.py
deleted file mode 100644 (file)
index 7561179..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2005-2008 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Nathan Binkert
-
-from m5.params import *
-from m5.proxy import *
-from MemObject import *
-
-class PhysicalMemory(MemObject):
-    type = 'PhysicalMemory'
-    port = VectorSlavePort("the access port")
-    range = Param.AddrRange(AddrRange('128MB'), "Device Address")
-    file = Param.String('', "memory mapped file")
-    latency = Param.Latency('30ns', "latency of an access")
-    latency_var = Param.Latency('0ns', "access variablity")
-    zero = Param.Bool(False, "zero initialize memory")
-    null = Param.Bool(False, "do not store data, always return zero")
index d30fd7fcbf82d280abc0b3d15e0eee11923de6d7..efb3c947a72a63c67139bb2cca24a5e1776144ea 100644 (file)
@@ -47,7 +47,10 @@ Source('fs_translating_port_proxy.cc')
 Source('se_translating_port_proxy.cc')
 
 if env['TARGET_ISA'] != 'no':
-    SimObject('PhysicalMemory.py')
+    SimObject('AbstractMemory.py')
+    SimObject('SimpleMemory.py')
+    Source('abstract_mem.cc')
+    Source('simple_mem.cc')
     Source('page_table.cc')
     Source('physical.cc')
 
diff --git a/src/mem/SimpleMemory.py b/src/mem/SimpleMemory.py
new file mode 100644 (file)
index 0000000..51de337
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright (c) 2012 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# Copyright (c) 2005-2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+#          Andreas Hansson
+
+from m5.params import *
+from AbstractMemory import *
+
+class SimpleMemory(AbstractMemory):
+    type = 'SimpleMemory'
+    port = VectorSlavePort("Slave ports")
+    latency = Param.Latency('30ns', "Request to response latency")
+    latency_var = Param.Latency('0ns', "Request to response latency variance")
diff --git a/src/mem/abstract_mem.cc b/src/mem/abstract_mem.cc
new file mode 100644 (file)
index 0000000..13a1183
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 2010-2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ron Dreslinski
+ *          Ali Saidi
+ *          Andreas Hansson
+ */
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include <cerrno>
+#include <cstdio>
+#include <iostream>
+#include <string>
+
+#include "arch/registers.hh"
+#include "config/the_isa.hh"
+#include "debug/LLSC.hh"
+#include "debug/MemoryAccess.hh"
+#include "mem/abstract_mem.hh"
+#include "mem/packet_access.hh"
+
+using namespace std;
+
+AbstractMemory::AbstractMemory(const Params *p) :
+    MemObject(p), range(params()->range), pmemAddr(NULL),
+    confTableReported(p->conf_table_reported), inAddrMap(p->in_addr_map)
+{
+    if (size() % TheISA::PageBytes != 0)
+        panic("Memory Size not divisible by page size\n");
+
+    if (params()->null)
+        return;
+
+    if (params()->file == "") {
+        int map_flags = MAP_ANON | MAP_PRIVATE;
+        pmemAddr = (uint8_t *)mmap(NULL, size(),
+                                   PROT_READ | PROT_WRITE, map_flags, -1, 0);
+    } else {
+        int map_flags = MAP_PRIVATE;
+        int fd = open(params()->file.c_str(), O_RDONLY);
+        long _size = lseek(fd, 0, SEEK_END);
+        if (_size != range.size()) {
+            warn("Specified size %d does not match file %s %d\n", range.size(),
+                 params()->file, _size);
+            range = RangeSize(range.start, _size);
+        }
+        lseek(fd, 0, SEEK_SET);
+        pmemAddr = (uint8_t *)mmap(NULL, roundUp(_size, sysconf(_SC_PAGESIZE)),
+                                   PROT_READ | PROT_WRITE, map_flags, fd, 0);
+    }
+
+    if (pmemAddr == (void *)MAP_FAILED) {
+        perror("mmap");
+        if (params()->file == "")
+            fatal("Could not mmap!\n");
+        else
+            fatal("Could not find file: %s\n", params()->file);
+    }
+
+    //If requested, initialize all the memory to 0
+    if (p->zero)
+        memset(pmemAddr, 0, size());
+}
+
+
+AbstractMemory::~AbstractMemory()
+{
+    if (pmemAddr)
+        munmap((char*)pmemAddr, size());
+}
+
+void
+AbstractMemory::regStats()
+{
+    using namespace Stats;
+
+    bytesRead
+        .name(name() + ".bytes_read")
+        .desc("Number of bytes read from this memory")
+        ;
+    bytesInstRead
+        .name(name() + ".bytes_inst_read")
+        .desc("Number of instructions bytes read from this memory")
+        ;
+    bytesWritten
+        .name(name() + ".bytes_written")
+        .desc("Number of bytes written to this memory")
+        ;
+    numReads
+        .name(name() + ".num_reads")
+        .desc("Number of read requests responded to by this memory")
+        ;
+    numWrites
+        .name(name() + ".num_writes")
+        .desc("Number of write requests responded to by this memory")
+        ;
+    numOther
+        .name(name() + ".num_other")
+        .desc("Number of other requests responded to by this memory")
+        ;
+    bwRead
+        .name(name() + ".bw_read")
+        .desc("Total read bandwidth from this memory (bytes/s)")
+        .precision(0)
+        .prereq(bytesRead)
+        ;
+    bwInstRead
+        .name(name() + ".bw_inst_read")
+        .desc("Instruction read bandwidth from this memory (bytes/s)")
+        .precision(0)
+        .prereq(bytesInstRead)
+        ;
+    bwWrite
+        .name(name() + ".bw_write")
+        .desc("Write bandwidth from this memory (bytes/s)")
+        .precision(0)
+        .prereq(bytesWritten)
+        ;
+    bwTotal
+        .name(name() + ".bw_total")
+        .desc("Total bandwidth to/from this memory (bytes/s)")
+        .precision(0)
+        .prereq(bwTotal)
+        ;
+    bwRead = bytesRead / simSeconds;
+    bwInstRead = bytesInstRead / simSeconds;
+    bwWrite = bytesWritten / simSeconds;
+    bwTotal = (bytesRead + bytesWritten) / simSeconds;
+}
+
+Range<Addr>
+AbstractMemory::getAddrRange()
+{
+    return range;
+}
+
+// Add load-locked to tracking list.  Should only be called if the
+// operation is a load and the LLSC flag is set.
+void
+AbstractMemory::trackLoadLocked(PacketPtr pkt)
+{
+    Request *req = pkt->req;
+    Addr paddr = LockedAddr::mask(req->getPaddr());
+
+    // first we check if we already have a locked addr for this
+    // xc.  Since each xc only gets one, we just update the
+    // existing record with the new address.
+    list<LockedAddr>::iterator i;
+
+    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
+        if (i->matchesContext(req)) {
+            DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n",
+                    req->contextId(), paddr);
+            i->addr = paddr;
+            return;
+        }
+    }
+
+    // no record for this xc: need to allocate a new one
+    DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n",
+            req->contextId(), paddr);
+    lockedAddrList.push_front(LockedAddr(req));
+}
+
+
+// Called on *writes* only... both regular stores and
+// store-conditional operations.  Check for conventional stores which
+// conflict with locked addresses, and for success/failure of store
+// conditionals.
+bool
+AbstractMemory::checkLockedAddrList(PacketPtr pkt)
+{
+    Request *req = pkt->req;
+    Addr paddr = LockedAddr::mask(req->getPaddr());
+    bool isLLSC = pkt->isLLSC();
+
+    // Initialize return value.  Non-conditional stores always
+    // succeed.  Assume conditional stores will fail until proven
+    // otherwise.
+    bool success = !isLLSC;
+
+    // Iterate over list.  Note that there could be multiple matching
+    // records, as more than one context could have done a load locked
+    // to this location.
+    list<LockedAddr>::iterator i = lockedAddrList.begin();
+
+    while (i != lockedAddrList.end()) {
+
+        if (i->addr == paddr) {
+            // we have a matching address
+
+            if (isLLSC && i->matchesContext(req)) {
+                // it's a store conditional, and as far as the memory
+                // system can tell, the requesting context's lock is
+                // still valid.
+                DPRINTF(LLSC, "StCond success: context %d addr %#x\n",
+                        req->contextId(), paddr);
+                success = true;
+            }
+
+            // Get rid of our record of this lock and advance to next
+            DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
+                    i->contextId, paddr);
+            i = lockedAddrList.erase(i);
+        }
+        else {
+            // no match: advance to next record
+            ++i;
+        }
+    }
+
+    if (isLLSC) {
+        req->setExtraData(success ? 1 : 0);
+    }
+
+    return success;
+}
+
+
+#if TRACING_ON
+
+#define CASE(A, T)                                                      \
+  case sizeof(T):                                                       \
+    DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n",   \
+            A, pkt->getSize(), pkt->getAddr(), pkt->get<T>());          \
+  break
+
+
+#define TRACE_PACKET(A)                                                 \
+    do {                                                                \
+        switch (pkt->getSize()) {                                       \
+          CASE(A, uint64_t);                                            \
+          CASE(A, uint32_t);                                            \
+          CASE(A, uint16_t);                                            \
+          CASE(A, uint8_t);                                             \
+          default:                                                      \
+            DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n",    \
+                    A, pkt->getSize(), pkt->getAddr());                 \
+            DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
+        }                                                               \
+    } while (0)
+
+#else
+
+#define TRACE_PACKET(A)
+
+#endif
+
+void
+AbstractMemory::access(PacketPtr pkt)
+{
+    assert(pkt->getAddr() >= range.start &&
+           (pkt->getAddr() + pkt->getSize() - 1) <= range.end);
+
+    if (pkt->memInhibitAsserted()) {
+        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
+                pkt->getAddr());
+        return;
+    }
+
+    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start;
+
+    if (pkt->cmd == MemCmd::SwapReq) {
+        TheISA::IntReg overwrite_val;
+        bool overwrite_mem;
+        uint64_t condition_val64;
+        uint32_t condition_val32;
+
+        if (!pmemAddr)
+            panic("Swap only works if there is real memory (i.e. null=False)");
+        assert(sizeof(TheISA::IntReg) >= pkt->getSize());
+
+        overwrite_mem = true;
+        // keep a copy of our possible write value, and copy what is at the
+        // memory address into the packet
+        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
+        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+
+        if (pkt->req->isCondSwap()) {
+            if (pkt->getSize() == sizeof(uint64_t)) {
+                condition_val64 = pkt->req->getExtraData();
+                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
+                                             sizeof(uint64_t));
+            } else if (pkt->getSize() == sizeof(uint32_t)) {
+                condition_val32 = (uint32_t)pkt->req->getExtraData();
+                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
+                                             sizeof(uint32_t));
+            } else
+                panic("Invalid size for conditional read/write\n");
+        }
+
+        if (overwrite_mem)
+            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
+
+        assert(!pkt->req->isInstFetch());
+        TRACE_PACKET("Read/Write");
+        numOther++;
+    } else if (pkt->isRead()) {
+        assert(!pkt->isWrite());
+        if (pkt->isLLSC()) {
+            trackLoadLocked(pkt);
+        }
+        if (pmemAddr)
+            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+        TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
+        numReads++;
+        bytesRead += pkt->getSize();
+        if (pkt->req->isInstFetch())
+            bytesInstRead += pkt->getSize();
+    } else if (pkt->isWrite()) {
+        if (writeOK(pkt)) {
+            if (pmemAddr)
+                memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+            assert(!pkt->req->isInstFetch());
+            TRACE_PACKET("Write");
+            numWrites++;
+            bytesWritten += pkt->getSize();
+        }
+    } else if (pkt->isInvalidate()) {
+        // no need to do anything
+    } else {
+        panic("unimplemented");
+    }
+
+    if (pkt->needsResponse()) {
+        pkt->makeResponse();
+    }
+}
+
+void
+AbstractMemory::functionalAccess(PacketPtr pkt)
+{
+    assert(pkt->getAddr() >= range.start &&
+           (pkt->getAddr() + pkt->getSize() - 1) <= range.end);
+
+    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start;
+
+    if (pkt->isRead()) {
+        if (pmemAddr)
+            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+        TRACE_PACKET("Read");
+        pkt->makeResponse();
+    } else if (pkt->isWrite()) {
+        if (pmemAddr)
+            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+        TRACE_PACKET("Write");
+        pkt->makeResponse();
+    } else if (pkt->isPrint()) {
+        Packet::PrintReqState *prs =
+            dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
+        // Need to call printLabels() explicitly since we're not going
+        // through printObj().
+        prs->printLabels();
+        // Right now we just print the single byte at the specified address.
+        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
+    } else {
+        panic("AbstractMemory: unimplemented functional command %s",
+              pkt->cmdString());
+    }
+}
+
+void
+AbstractMemory::serialize(ostream &os)
+{
+    if (!pmemAddr)
+        return;
+
+    gzFile compressedMem;
+    string filename = name() + ".physmem";
+    long _size = range.size();
+
+    SERIALIZE_SCALAR(filename);
+    SERIALIZE_SCALAR(_size);
+
+    // write memory file
+    string thefile = Checkpoint::dir() + "/" + filename.c_str();
+    int fd = creat(thefile.c_str(), 0664);
+    if (fd < 0) {
+        perror("creat");
+        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
+    }
+
+    compressedMem = gzdopen(fd, "wb");
+    if (compressedMem == NULL)
+        fatal("Insufficient memory to allocate compression state for %s\n",
+                filename);
+
+    if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) {
+        fatal("Write failed on physical memory checkpoint file '%s'\n",
+              filename);
+    }
+
+    if (gzclose(compressedMem))
+        fatal("Close failed on physical memory checkpoint file '%s'\n",
+              filename);
+
+    list<LockedAddr>::iterator i = lockedAddrList.begin();
+
+    vector<Addr> lal_addr;
+    vector<int> lal_cid;
+    while (i != lockedAddrList.end()) {
+        lal_addr.push_back(i->addr);
+        lal_cid.push_back(i->contextId);
+        i++;
+    }
+    arrayParamOut(os, "lal_addr", lal_addr);
+    arrayParamOut(os, "lal_cid", lal_cid);
+}
+
+void
+AbstractMemory::unserialize(Checkpoint *cp, const string &section)
+{
+    if (!pmemAddr)
+        return;
+
+    gzFile compressedMem;
+    long *tempPage;
+    long *pmem_current;
+    uint64_t curSize;
+    uint32_t bytesRead;
+    const uint32_t chunkSize = 16384;
+
+    string filename;
+
+    UNSERIALIZE_SCALAR(filename);
+
+    filename = cp->cptDir + "/" + filename;
+
+    // mmap memoryfile
+    int fd = open(filename.c_str(), O_RDONLY);
+    if (fd < 0) {
+        perror("open");
+        fatal("Can't open physical memory checkpoint file '%s'", filename);
+    }
+
+    compressedMem = gzdopen(fd, "rb");
+    if (compressedMem == NULL)
+        fatal("Insufficient memory to allocate compression state for %s\n",
+                filename);
+
+    // unmap file that was mmapped in the constructor
+    // This is done here to make sure that gzip and open don't muck with our
+    // nice large space of memory before we reallocate it
+    munmap((char*)pmemAddr, size());
+
+    long _size;
+    UNSERIALIZE_SCALAR(_size);
+    if (_size > params()->range.size())
+        fatal("Memory size has changed! size %lld, param size %lld\n",
+              _size, params()->range.size());
+
+    pmemAddr = (uint8_t *)mmap(NULL, size(),
+        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+
+    if (pmemAddr == (void *)MAP_FAILED) {
+        perror("mmap");
+        fatal("Could not mmap physical memory!\n");
+    }
+
+    curSize = 0;
+    tempPage = (long*)malloc(chunkSize);
+    if (tempPage == NULL)
+        fatal("Unable to malloc memory to read file %s\n", filename);
+
+    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
+    while (curSize < size()) {
+        bytesRead = gzread(compressedMem, tempPage, chunkSize);
+        if (bytesRead == 0)
+            break;
+
+        assert(bytesRead % sizeof(long) == 0);
+
+        for (uint32_t x = 0; x < bytesRead / sizeof(long); x++)
+        {
+             if (*(tempPage+x) != 0) {
+                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
+                 *pmem_current = *(tempPage+x);
+             }
+        }
+        curSize += bytesRead;
+    }
+
+    free(tempPage);
+
+    if (gzclose(compressedMem))
+        fatal("Close failed on physical memory checkpoint file '%s'\n",
+              filename);
+
+    vector<Addr> lal_addr;
+    vector<int> lal_cid;
+    arrayParamIn(cp, section, "lal_addr", lal_addr);
+    arrayParamIn(cp, section, "lal_cid", lal_cid);
+    for(int i = 0; i < lal_addr.size(); i++)
+        lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i]));
+}
diff --git a/src/mem/abstract_mem.hh b/src/mem/abstract_mem.hh
new file mode 100644 (file)
index 0000000..42ad08e
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ron Dreslinski
+ *          Andreas Hansson
+ */
+
+/**
+ * @file
+ * AbstractMemory declaration
+ */
+
+#ifndef __ABSTRACT_MEMORY_HH__
+#define __ABSTRACT_MEMORY_HH__
+
+#include "mem/mem_object.hh"
+#include "params/AbstractMemory.hh"
+#include "sim/stats.hh"
+
+/**
+ * An abstract memory represents a contiguous block of physical
+ * memory, with an associated address range, and also provides basic
+ * functionality for reading and writing this memory without any
+ * timing information. It is a MemObject since any subclass must have
+ * at least one slave port.
+ */
+class AbstractMemory : public MemObject
+{
+  protected:
+
+    // Address range of this memory
+    Range<Addr> range;
+
+    // Pointer to host memory used to implement this memory
+    uint8_t* pmemAddr;
+
+    // Enable specific memories to be reported to the configuration table
+    bool confTableReported;
+
+    // Should the memory appear in the global address map
+    bool inAddrMap;
+
+    class LockedAddr {
+
+      public:
+        // on alpha, minimum LL/SC granularity is 16 bytes, so lower
+        // bits need to masked off.
+        static const Addr Addr_Mask = 0xf;
+
+        static Addr mask(Addr paddr) { return (paddr & ~Addr_Mask); }
+
+        Addr addr;      // locked address
+        int contextId;     // locking hw context
+
+        // check for matching execution context
+        bool matchesContext(Request *req)
+        {
+            return (contextId == req->contextId());
+        }
+
+        LockedAddr(Request *req) : addr(mask(req->getPaddr())),
+                                   contextId(req->contextId())
+        {
+        }
+        // constructor for unserialization use
+        LockedAddr(Addr _addr, int _cid) : addr(_addr), contextId(_cid)
+        {
+        }
+    };
+
+    std::list<LockedAddr> lockedAddrList;
+
+    // helper function for checkLockedAddrs(): we really want to
+    // inline a quick check for an empty locked addr list (hopefully
+    // the common case), and do the full list search (if necessary) in
+    // this out-of-line function
+    bool checkLockedAddrList(PacketPtr pkt);
+
+    // Record the address of a load-locked operation so that we can
+    // clear the execution context's lock flag if a matching store is
+    // performed
+    void trackLoadLocked(PacketPtr pkt);
+
+    // Compare a store address with any locked addresses so we can
+    // clear the lock flag appropriately.  Return value set to 'false'
+    // if store operation should be suppressed (because it was a
+    // conditional store and the address was no longer locked by the
+    // requesting execution context), 'true' otherwise.  Note that
+    // this method must be called on *all* stores since even
+    // non-conditional stores must clear any matching lock addresses.
+    bool writeOK(PacketPtr pkt) {
+        Request *req = pkt->req;
+        if (lockedAddrList.empty()) {
+            // no locked addrs: nothing to check, store_conditional fails
+            bool isLLSC = pkt->isLLSC();
+            if (isLLSC) {
+                req->setExtraData(0);
+            }
+            return !isLLSC; // only do write if not an sc
+        } else {
+            // iterate over list...
+            return checkLockedAddrList(pkt);
+        }
+    }
+
+    /** Number of total bytes read from this memory */
+    Stats::Scalar bytesRead;
+    /** Number of instruction bytes read from this memory */
+    Stats::Scalar bytesInstRead;
+    /** Number of bytes written to this memory */
+    Stats::Scalar bytesWritten;
+    /** Number of read requests */
+    Stats::Scalar numReads;
+    /** Number of write requests */
+    Stats::Scalar numWrites;
+    /** Number of other requests */
+    Stats::Scalar numOther;
+    /** Read bandwidth from this memory */
+    Stats::Formula bwRead;
+    /** Read bandwidth from this memory */
+    Stats::Formula bwInstRead;
+    /** Write bandwidth from this memory */
+    Stats::Formula bwWrite;
+    /** Total bandwidth from this memory */
+    Stats::Formula bwTotal;
+
+  private:
+
+    // Prevent copying
+    AbstractMemory(const AbstractMemory&);
+
+    // Prevent assignment
+    AbstractMemory& operator=(const AbstractMemory&);
+
+  public:
+
+    typedef AbstractMemoryParams Params;
+
+    AbstractMemory(const Params* p);
+    virtual ~AbstractMemory();
+
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+
+    /**
+     * Get the address range
+     *
+     * @return a single contigous address range
+     */
+    Range<Addr> getAddrRange();
+
+    /**
+     * Get the memory size.
+     *
+     * @return the size of the memory
+     */
+    uint64_t size() { return range.size(); }
+
+    /**
+     * Get the start address.
+     *
+     * @return the start address of the memory
+     */
+    Addr start() { return range.start; }
+
+    /**
+     *  Should this memory be passed to the kernel and part of the OS
+     *  physical memory layout.
+     *
+     * @return if this memory is reported
+     */
+    bool isConfReported() const { return confTableReported; }
+
+    /**
+     * Some memories are used as shadow memories or should for other
+     * reasons not be part of the global address map.
+     *
+     * @return if this memory is part of the address map
+     */
+    bool isInAddrMap() const { return inAddrMap; }
+
+    /**
+     * Perform an untimed memory access and update all the state
+     * (e.g. locked addresses) and statistics accordingly. The packet
+     * is turned into a response if required.
+     *
+     * @param pkt Packet performing the access
+     */
+    void access(PacketPtr pkt);
+
+    /**
+     * Perform an untimed memory read or write without changing
+     * anything but the memory itself. No stats are affected by this
+     * access. In addition to normal accesses this also facilitates
+     * print requests.
+     *
+     * @param pkt Packet performing the access
+     */
+    void functionalAccess(PacketPtr pkt);
+
+    /**
+     * Register Statistics
+     */
+    virtual void regStats();
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif //__ABSTRACT_MEMORY_HH__
index 821a3635bfb6cb77205a4240111612032e6205dd..6da77953835ef4eaad3e3a50c2440ed8cca7a971 100644 (file)
@@ -331,7 +331,7 @@ MSHR::handleSnoop(PacketPtr pkt, Counter _order)
         //    to forward the snoop up the hierarchy after the current
         //    transaction completes.
         
-        // Actual target device (typ. PhysicalMemory) will delete the
+        // Actual target device (typ. a memory) will delete the
         // packet on reception, so we need to save a copy here.
         PacketPtr cp_pkt = new Packet(pkt, true);
         targets->add(cp_pkt, curTick(), _order, Target::FromSnoop,
index 78181b7df98380aea8e4e992a6ba23b4fa5f3b9c..5f92976f9dedc35ed7b45c32bd6d91dd8cb23eef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 ARM Limited
+ * Copyright (c) 2012 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -11,9 +11,6 @@
  * unmodified and in its entirety in all distributions of the software,
  * modified or unmodified, in source code or in binary form.
  *
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * met: redistributions of source code must retain the above copyright
  * (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: Ron Dreslinski
- *          Ali Saidi
+ * Authors: Andreas Hansson
  */
 
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/user.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <zlib.h>
-
-#include <cerrno>
-#include <cstdio>
-#include <iostream>
-#include <string>
-
-#include "arch/isa_traits.hh"
-#include "arch/registers.hh"
-#include "base/intmath.hh"
-#include "base/misc.hh"
-#include "base/random.hh"
-#include "base/types.hh"
-#include "config/the_isa.hh"
-#include "debug/LLSC.hh"
-#include "debug/MemoryAccess.hh"
-#include "mem/packet_access.hh"
+#include "debug/BusAddrRanges.hh"
 #include "mem/physical.hh"
-#include "sim/eventq.hh"
 
 using namespace std;
-using namespace TheISA;
-
-PhysicalMemory::PhysicalMemory(const Params *p)
-    : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var),
-      _size(params()->range.size()), _start(params()->range.start)
-{
-    if (size() % TheISA::PageBytes != 0)
-        panic("Memory Size not divisible by page size\n");
-
-    // create the appropriate number of ports
-    for (int i = 0; i < p->port_port_connection_count; ++i) {
-        ports.push_back(new MemoryPort(csprintf("%s-port%d", name(), i),
-                                       this));
-    }
-
-    if (params()->null)
-        return;
-
-
-    if (params()->file == "") {
-        int map_flags = MAP_ANON | MAP_PRIVATE;
-        pmemAddr = (uint8_t *)mmap(NULL, size(),
-                                   PROT_READ | PROT_WRITE, map_flags, -1, 0);
-    } else {
-        int map_flags = MAP_PRIVATE;
-        int fd = open(params()->file.c_str(), O_RDONLY);
-        _size = lseek(fd, 0, SEEK_END);
-        lseek(fd, 0, SEEK_SET);
-        pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)),
-                                   PROT_READ | PROT_WRITE, map_flags, fd, 0);
-    }
-
-    if (pmemAddr == (void *)MAP_FAILED) {
-        perror("mmap");
-        if (params()->file == "")
-            fatal("Could not mmap!\n");
-        else
-            fatal("Could not find file: %s\n", params()->file);
-    }
-
-    //If requested, initialize all the memory to 0
-    if (p->zero)
-        memset(pmemAddr, 0, size());
-}
-
-void
-PhysicalMemory::init()
-{
-    for (PortIterator p = ports.begin(); p != ports.end(); ++p) {
-        if (!(*p)->isConnected()) {
-            fatal("PhysicalMemory port %s is unconnected!\n", (*p)->name());
-        } else {
-            (*p)->sendRangeChange();
-        }
-    }
-}
-
-PhysicalMemory::~PhysicalMemory()
-{
-    if (pmemAddr)
-        munmap((char*)pmemAddr, size());
-}
-
-void
-PhysicalMemory::regStats()
-{
-    using namespace Stats;
-
-    bytesRead
-        .name(name() + ".bytes_read")
-        .desc("Number of bytes read from this memory")
-        ;
-    bytesInstRead
-        .name(name() + ".bytes_inst_read")
-        .desc("Number of instructions bytes read from this memory")
-        ;
-    bytesWritten
-        .name(name() + ".bytes_written")
-        .desc("Number of bytes written to this memory")
-        ;
-    numReads
-        .name(name() + ".num_reads")
-        .desc("Number of read requests responded to by this memory")
-        ;
-    numWrites
-        .name(name() + ".num_writes")
-        .desc("Number of write requests responded to by this memory")
-        ;
-    numOther
-        .name(name() + ".num_other")
-        .desc("Number of other requests responded to by this memory")
-        ;
-    bwRead
-        .name(name() + ".bw_read")
-        .desc("Total read bandwidth from this memory (bytes/s)")
-        .precision(0)
-        .prereq(bytesRead)
-        ;
-    bwInstRead
-        .name(name() + ".bw_inst_read")
-        .desc("Instruction read bandwidth from this memory (bytes/s)")
-        .precision(0)
-        .prereq(bytesInstRead)
-        ;
-    bwWrite
-        .name(name() + ".bw_write")
-        .desc("Write bandwidth from this memory (bytes/s)")
-        .precision(0)
-        .prereq(bytesWritten)
-        ;
-    bwTotal
-        .name(name() + ".bw_total")
-        .desc("Total bandwidth to/from this memory (bytes/s)")
-        .precision(0)
-        .prereq(bwTotal)
-        ;
-    bwRead = bytesRead / simSeconds;
-    bwInstRead = bytesInstRead / simSeconds;
-    bwWrite = bytesWritten / simSeconds;
-    bwTotal = (bytesRead + bytesWritten) / simSeconds;
-}
 
-unsigned
-PhysicalMemory::deviceBlockSize() const
-{
-    //Can accept anysize request
-    return 0;
-}
-
-Tick
-PhysicalMemory::calculateLatency(PacketPtr pkt)
-{
-    Tick latency = lat;
-    if (lat_var != 0)
-        latency += random_mt.random<Tick>(0, lat_var);
-    return latency;
-}
-
-
-
-// Add load-locked to tracking list.  Should only be called if the
-// operation is a load and the LLSC flag is set.
-void
-PhysicalMemory::trackLoadLocked(PacketPtr pkt)
+PhysicalMemory::PhysicalMemory(const vector<AbstractMemory*>& _memories) :
+    size(0)
 {
-    Request *req = pkt->req;
-    Addr paddr = LockedAddr::mask(req->getPaddr());
+    for (vector<AbstractMemory*>::const_iterator m = _memories.begin();
+         m != _memories.end(); ++m) {
+        // only add the memory if it is part of the global address map
+        if ((*m)->isInAddrMap()) {
+            memories.push_back(*m);
 
-    // first we check if we already have a locked addr for this
-    // xc.  Since each xc only gets one, we just update the
-    // existing record with the new address.
-    list<LockedAddr>::iterator i;
+            // calculate the total size once and for all
+            size += (*m)->size();
 
-    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
-        if (i->matchesContext(req)) {
-            DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n",
-                    req->contextId(), paddr);
-            i->addr = paddr;
-            return;
+            // add the range to our interval tree and make sure it does not
+            // intersect an existing range
+            if (addrMap.insert((*m)->getAddrRange(), *m) == addrMap.end())
+                fatal("Memory address range for %s is overlapping\n",
+                      (*m)->name());
         }
+        DPRINTF(BusAddrRanges,
+                "Skipping memory %s that is not in global address map\n",
+                (*m)->name());
     }
-
-    // no record for this xc: need to allocate a new one
-    DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n",
-            req->contextId(), paddr);
-    lockedAddrList.push_front(LockedAddr(req));
+    rangeCache.invalidate();
 }
 
-
-// Called on *writes* only... both regular stores and
-// store-conditional operations.  Check for conventional stores which
-// conflict with locked addresses, and for success/failure of store
-// conditionals.
 bool
-PhysicalMemory::checkLockedAddrList(PacketPtr pkt)
-{
-    Request *req = pkt->req;
-    Addr paddr = LockedAddr::mask(req->getPaddr());
-    bool isLLSC = pkt->isLLSC();
-
-    // Initialize return value.  Non-conditional stores always
-    // succeed.  Assume conditional stores will fail until proven
-    // otherwise.
-    bool success = !isLLSC;
-
-    // Iterate over list.  Note that there could be multiple matching
-    // records, as more than one context could have done a load locked
-    // to this location.
-    list<LockedAddr>::iterator i = lockedAddrList.begin();
-
-    while (i != lockedAddrList.end()) {
-
-        if (i->addr == paddr) {
-            // we have a matching address
-
-            if (isLLSC && i->matchesContext(req)) {
-                // it's a store conditional, and as far as the memory
-                // system can tell, the requesting context's lock is
-                // still valid.
-                DPRINTF(LLSC, "StCond success: context %d addr %#x\n",
-                        req->contextId(), paddr);
-                success = true;
-            }
-
-            // Get rid of our record of this lock and advance to next
-            DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
-                    i->contextId, paddr);
-            i = lockedAddrList.erase(i);
-        }
-        else {
-            // no match: advance to next record
-            ++i;
+PhysicalMemory::isMemAddr(Addr addr) const
+{
+    // see if the address is within the last matched range
+    if (addr != rangeCache) {
+        // lookup in the interval tree
+        range_map<Addr, AbstractMemory*>::const_iterator r =
+            addrMap.find(addr);
+        if (r == addrMap.end()) {
+            // not in the cache, and not in the tree
+            return false;
         }
+        // the range is in the tree, update the cache
+        rangeCache = r->first;
     }
 
-    if (isLLSC) {
-        req->setExtraData(success ? 1 : 0);
-    }
-
-    return success;
-}
-
-
-#if TRACING_ON
-
-#define CASE(A, T)                                                      \
-  case sizeof(T):                                                       \
-    DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n",   \
-            A, pkt->getSize(), pkt->getAddr(), pkt->get<T>());          \
-  break
-
-
-#define TRACE_PACKET(A)                                                 \
-    do {                                                                \
-        switch (pkt->getSize()) {                                       \
-          CASE(A, uint64_t);                                            \
-          CASE(A, uint32_t);                                            \
-          CASE(A, uint16_t);                                            \
-          CASE(A, uint8_t);                                             \
-          default:                                                      \
-            DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n",    \
-                    A, pkt->getSize(), pkt->getAddr());                 \
-            DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
-        }                                                               \
-    } while (0)
-
-#else
-
-#define TRACE_PACKET(A)
-
-#endif
-
-Tick
-PhysicalMemory::doAtomicAccess(PacketPtr pkt)
-{
-    assert(pkt->getAddr() >= start() &&
-           pkt->getAddr() + pkt->getSize() <= start() + size());
-
-    if (pkt->memInhibitAsserted()) {
-        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
-                pkt->getAddr());
-        return 0;
-    }
-
-    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
-
-    if (pkt->cmd == MemCmd::SwapReq) {
-        IntReg overwrite_val;
-        bool overwrite_mem;
-        uint64_t condition_val64;
-        uint32_t condition_val32;
-
-        if (!pmemAddr)
-            panic("Swap only works if there is real memory (i.e. null=False)");
-        assert(sizeof(IntReg) >= pkt->getSize());
-
-        overwrite_mem = true;
-        // keep a copy of our possible write value, and copy what is at the
-        // memory address into the packet
-        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
-        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+    assert(addrMap.find(addr) != addrMap.end());
 
-        if (pkt->req->isCondSwap()) {
-            if (pkt->getSize() == sizeof(uint64_t)) {
-                condition_val64 = pkt->req->getExtraData();
-                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
-                                             sizeof(uint64_t));
-            } else if (pkt->getSize() == sizeof(uint32_t)) {
-                condition_val32 = (uint32_t)pkt->req->getExtraData();
-                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
-                                             sizeof(uint32_t));
-            } else
-                panic("Invalid size for conditional read/write\n");
-        }
-
-        if (overwrite_mem)
-            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
-
-        assert(!pkt->req->isInstFetch());
-        TRACE_PACKET("Read/Write");
-        numOther++;
-    } else if (pkt->isRead()) {
-        assert(!pkt->isWrite());
-        if (pkt->isLLSC()) {
-            trackLoadLocked(pkt);
-        }
-        if (pmemAddr)
-            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
-        TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
-        numReads++;
-        bytesRead += pkt->getSize();
-        if (pkt->req->isInstFetch())
-            bytesInstRead += pkt->getSize();
-    } else if (pkt->isWrite()) {
-        if (writeOK(pkt)) {
-            if (pmemAddr)
-                memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
-            assert(!pkt->req->isInstFetch());
-            TRACE_PACKET("Write");
-            numWrites++;
-            bytesWritten += pkt->getSize();
-        }
-    } else if (pkt->isInvalidate()) {
-        //upgrade or invalidate
-        if (pkt->needsResponse()) {
-            pkt->makeAtomicResponse();
-        }
-    } else {
-        panic("unimplemented");
-    }
-
-    if (pkt->needsResponse()) {
-        pkt->makeAtomicResponse();
-    }
-    return calculateLatency(pkt);
-}
-
-
-void
-PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
-{
-    assert(pkt->getAddr() >= start() &&
-           pkt->getAddr() + pkt->getSize() <= start() + size());
-
-
-    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
-
-    if (pkt->isRead()) {
-        if (pmemAddr)
-            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
-        TRACE_PACKET("Read");
-        pkt->makeAtomicResponse();
-    } else if (pkt->isWrite()) {
-        if (pmemAddr)
-            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
-        TRACE_PACKET("Write");
-        pkt->makeAtomicResponse();
-    } else if (pkt->isPrint()) {
-        Packet::PrintReqState *prs =
-            dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
-        // Need to call printLabels() explicitly since we're not going
-        // through printObj().
-        prs->printLabels();
-        // Right now we just print the single byte at the specified address.
-        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
-    } else {
-        panic("PhysicalMemory: unimplemented functional command %s",
-              pkt->cmdString());
-    }
-}
-
-
-SlavePort &
-PhysicalMemory::getSlavePort(const std::string &if_name, int idx)
-{
-    if (if_name != "port") {
-        return MemObject::getSlavePort(if_name, idx);
-    } else {
-        if (idx >= static_cast<int>(ports.size())) {
-            fatal("PhysicalMemory::getSlavePort: unknown index %d\n", idx);
-        }
-
-        return *ports[idx];
-    }
-}
-
-PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
-                                       PhysicalMemory *_memory)
-    : SimpleTimingPort(_name, _memory), memory(_memory)
-{ }
-
-AddrRangeList
-PhysicalMemory::MemoryPort::getAddrRanges()
-{
-    return memory->getAddrRanges();
+    // either matched the cache or found in the tree
+    return true;
 }
 
 AddrRangeList
-PhysicalMemory::getAddrRanges()
+PhysicalMemory::getConfAddrRanges() const
 {
+    // this could be done once in the constructor, but since it is unlikely to
+    // be called more than once the iteration should not be a problem
     AddrRangeList ranges;
-    ranges.push_back(RangeSize(start(), size()));
-    return ranges;
-}
-
-unsigned
-PhysicalMemory::MemoryPort::deviceBlockSize() const
-{
-    return memory->deviceBlockSize();
-}
-
-Tick
-PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
-{
-    return memory->doAtomicAccess(pkt);
-}
-
-void
-PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
-{
-    pkt->pushLabel(memory->name());
-
-    if (!queue.checkFunctional(pkt)) {
-        // Default implementation of SimpleTimingPort::recvFunctional()
-        // calls recvAtomic() and throws away the latency; we can save a
-        // little here by just not calculating the latency.
-        memory->doFunctionalAccess(pkt);
-    }
-
-    pkt->popLabel();
-}
-
-unsigned int
-PhysicalMemory::drain(Event *de)
-{
-    int count = 0;
-    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
-        count += (*pi)->drain(de);
+    for (vector<AbstractMemory*>::const_iterator m = memories.begin();
+         m != memories.end(); ++m) {
+        if ((*m)->isConfReported()) {
+            ranges.push_back((*m)->getAddrRange());
+        }
     }
 
-    if (count)
-        changeState(Draining);
-    else
-        changeState(Drained);
-    return count;
+    return ranges;
 }
 
 void
-PhysicalMemory::serialize(ostream &os)
+PhysicalMemory::access(PacketPtr pkt)
 {
-    if (!pmemAddr)
-        return;
-
-    gzFile compressedMem;
-    string filename = name() + ".physmem";
-
-    SERIALIZE_SCALAR(filename);
-    SERIALIZE_SCALAR(_size);
-
-    // write memory file
-    string thefile = Checkpoint::dir() + "/" + filename.c_str();
-    int fd = creat(thefile.c_str(), 0664);
-    if (fd < 0) {
-        perror("creat");
-        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
-    }
-
-    compressedMem = gzdopen(fd, "wb");
-    if (compressedMem == NULL)
-        fatal("Insufficient memory to allocate compression state for %s\n",
-                filename);
-
-    if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) {
-        fatal("Write failed on physical memory checkpoint file '%s'\n",
-              filename);
-    }
-
-    if (gzclose(compressedMem))
-        fatal("Close failed on physical memory checkpoint file '%s'\n",
-              filename);
-
-    list<LockedAddr>::iterator i = lockedAddrList.begin();
-
-    vector<Addr> lal_addr;
-    vector<int> lal_cid;
-    while (i != lockedAddrList.end()) {
-        lal_addr.push_back(i->addr);
-        lal_cid.push_back(i->contextId);
-        i++;
-    }
-    arrayParamOut(os, "lal_addr", lal_addr);
-    arrayParamOut(os, "lal_cid", lal_cid);
+    assert(pkt->isRequest());
+    Addr addr = pkt->getAddr();
+    range_map<Addr, AbstractMemory*>::const_iterator m = addrMap.find(addr);
+    assert(m != addrMap.end());
+    m->second->access(pkt);
 }
 
 void
-PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
-{
-    if (!pmemAddr)
-        return;
-
-    gzFile compressedMem;
-    long *tempPage;
-    long *pmem_current;
-    uint64_t curSize;
-    uint32_t bytesRead;
-    const uint32_t chunkSize = 16384;
-
-    string filename;
-
-    UNSERIALIZE_SCALAR(filename);
-
-    filename = cp->cptDir + "/" + filename;
-
-    // mmap memoryfile
-    int fd = open(filename.c_str(), O_RDONLY);
-    if (fd < 0) {
-        perror("open");
-        fatal("Can't open physical memory checkpoint file '%s'", filename);
-    }
-
-    compressedMem = gzdopen(fd, "rb");
-    if (compressedMem == NULL)
-        fatal("Insufficient memory to allocate compression state for %s\n",
-                filename);
-
-    // unmap file that was mmapped in the constructor
-    // This is done here to make sure that gzip and open don't muck with our
-    // nice large space of memory before we reallocate it
-    munmap((char*)pmemAddr, size());
-
-    UNSERIALIZE_SCALAR(_size);
-    if (size() > params()->range.size())
-        fatal("Memory size has changed! size %lld, param size %lld\n",
-              size(), params()->range.size());
-
-    pmemAddr = (uint8_t *)mmap(NULL, size(),
-        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
-
-    if (pmemAddr == (void *)MAP_FAILED) {
-        perror("mmap");
-        fatal("Could not mmap physical memory!\n");
-    }
-
-    curSize = 0;
-    tempPage = (long*)malloc(chunkSize);
-    if (tempPage == NULL)
-        fatal("Unable to malloc memory to read file %s\n", filename);
-
-    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
-    while (curSize < size()) {
-        bytesRead = gzread(compressedMem, tempPage, chunkSize);
-        if (bytesRead == 0)
-            break;
-
-        assert(bytesRead % sizeof(long) == 0);
-
-        for (uint32_t x = 0; x < bytesRead / sizeof(long); x++)
-        {
-             if (*(tempPage+x) != 0) {
-                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
-                 *pmem_current = *(tempPage+x);
-             }
-        }
-        curSize += bytesRead;
-    }
-
-    free(tempPage);
-
-    if (gzclose(compressedMem))
-        fatal("Close failed on physical memory checkpoint file '%s'\n",
-              filename);
-
-    vector<Addr> lal_addr;
-    vector<int> lal_cid;
-    arrayParamIn(cp, section, "lal_addr", lal_addr);
-    arrayParamIn(cp, section, "lal_cid", lal_cid);
-    for(int i = 0; i < lal_addr.size(); i++)
-        lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i]));
-}
-
-PhysicalMemory *
-PhysicalMemoryParams::create()
+PhysicalMemory::functionalAccess(PacketPtr pkt)
 {
-    return new PhysicalMemory(this);
+    assert(pkt->isRequest());
+    Addr addr = pkt->getAddr();
+    range_map<Addr, AbstractMemory*>::const_iterator m = addrMap.find(addr);
+    assert(m != addrMap.end());
+    m->second->functionalAccess(pkt);
 }
index 23d4052fa9b25eef60ce8fb67d43bb4626bacddb..e78b1d2da3342ee52b88827310f2a173bf4ab499 100644 (file)
@@ -1,6 +1,15 @@
 /*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * (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: Ron Dreslinski
- */
-
-/* @file
+ * Authors: Andreas Hansson
  */
 
 #ifndef __PHYSICAL_MEMORY_HH__
 #define __PHYSICAL_MEMORY_HH__
 
-#include <map>
-#include <string>
-
-#include "base/range.hh"
-#include "base/statistics.hh"
-#include "mem/mem_object.hh"
+#include "base/range_map.hh"
+#include "mem/abstract_mem.hh"
 #include "mem/packet.hh"
-#include "mem/tport.hh"
-#include "params/PhysicalMemory.hh"
-#include "sim/eventq.hh"
-#include "sim/stats.hh"
-
-//
-// Functional model for a contiguous block of physical memory. (i.e. RAM)
-//
-class PhysicalMemory : public MemObject
-{
-  protected:
-
-    class MemoryPort : public SimpleTimingPort
-    {
-        PhysicalMemory *memory;
-
-      public:
 
-        MemoryPort(const std::string &_name, PhysicalMemory *_memory);
-
-      protected:
+/**
+ * The physical memory encapsulates all memories in the system and
+ * provides basic functionality for accessing those memories without
+ * going through the memory system and interconnect.
+ */
+class PhysicalMemory
+{
 
-        virtual Tick recvAtomic(PacketPtr pkt);
+  private:
 
-        virtual void recvFunctional(PacketPtr pkt);
+    // Global address map
+    range_map<Addr, AbstractMemory* > addrMap;
 
-        virtual AddrRangeList getAddrRanges();
+    // a mutable cache for the last range that matched an address
+    mutable Range<Addr> rangeCache;
 
-        virtual unsigned deviceBlockSize() const;
-    };
+    // All address-mapped memories
+    std::vector<AbstractMemory*> memories;
 
-    int numPorts;
+    // The total memory size
+    uint64_t size;
 
+    // Prevent copying
+    PhysicalMemory(const PhysicalMemory&);
 
-  private:
-    // prevent copying of a MainMemory object
-    PhysicalMemory(const PhysicalMemory &specmem);
-    const PhysicalMemory &operator=(const PhysicalMemory &specmem);
-
-  protected:
-
-    class LockedAddr {
-      public:
-        // on alpha, minimum LL/SC granularity is 16 bytes, so lower
-        // bits need to masked off.
-        static const Addr Addr_Mask = 0xf;
-
-        static Addr mask(Addr paddr) { return (paddr & ~Addr_Mask); }
-
-        Addr addr;      // locked address
-        int contextId;     // locking hw context
-
-        // check for matching execution context
-        bool matchesContext(Request *req)
-        {
-            return (contextId == req->contextId());
-        }
-
-        LockedAddr(Request *req)
-            : addr(mask(req->getPaddr())),
-              contextId(req->contextId())
-        {
-        }
-        // constructor for unserialization use
-        LockedAddr(Addr _addr, int _cid)
-            : addr(_addr), contextId(_cid)
-        {
-        }
-    };
-
-    std::list<LockedAddr> lockedAddrList;
-
-    // helper function for checkLockedAddrs(): we really want to
-    // inline a quick check for an empty locked addr list (hopefully
-    // the common case), and do the full list search (if necessary) in
-    // this out-of-line function
-    bool checkLockedAddrList(PacketPtr pkt);
-
-    // Record the address of a load-locked operation so that we can
-    // clear the execution context's lock flag if a matching store is
-    // performed
-    void trackLoadLocked(PacketPtr pkt);
-
-    // Compare a store address with any locked addresses so we can
-    // clear the lock flag appropriately.  Return value set to 'false'
-    // if store operation should be suppressed (because it was a
-    // conditional store and the address was no longer locked by the
-    // requesting execution context), 'true' otherwise.  Note that
-    // this method must be called on *all* stores since even
-    // non-conditional stores must clear any matching lock addresses.
-    bool writeOK(PacketPtr pkt) {
-        Request *req = pkt->req;
-        if (lockedAddrList.empty()) {
-            // no locked addrs: nothing to check, store_conditional fails
-            bool isLLSC = pkt->isLLSC();
-            if (isLLSC) {
-                req->setExtraData(0);
-            }
-            return !isLLSC; // only do write if not an sc
-        } else {
-            // iterate over list...
-            return checkLockedAddrList(pkt);
-        }
-    }
-
-    uint8_t *pmemAddr;
-    Tick lat;
-    Tick lat_var;
-    std::vector<MemoryPort*> ports;
-    typedef std::vector<MemoryPort*>::iterator PortIterator;
-
-    uint64_t _size;
-    uint64_t _start;
-
-    /** Number of total bytes read from this memory */
-    Stats::Scalar bytesRead;
-    /** Number of instruction bytes read from this memory */
-    Stats::Scalar bytesInstRead;
-    /** Number of bytes written to this memory */
-    Stats::Scalar bytesWritten;
-    /** Number of read requests */
-    Stats::Scalar numReads;
-    /** Number of write requests */
-    Stats::Scalar numWrites;
-    /** Number of other requests */
-    Stats::Scalar numOther;
-    /** Read bandwidth from this memory */
-    Stats::Formula bwRead;
-    /** Read bandwidth from this memory */
-    Stats::Formula bwInstRead;
-    /** Write bandwidth from this memory */
-    Stats::Formula bwWrite;
-    /** Total bandwidth from this memory */
-    Stats::Formula bwTotal;
+    // Prevent assignment
+    PhysicalMemory& operator=(const PhysicalMemory&);
 
   public:
-    uint64_t size() { return _size; }
-    uint64_t start() { return _start; }
 
-  public:
-    typedef PhysicalMemoryParams Params;
-    PhysicalMemory(const Params *p);
-    virtual ~PhysicalMemory();
-
-    const Params *
-    params() const
-    {
-        return dynamic_cast<const Params *>(_params);
-    }
-
-  public:
-    unsigned deviceBlockSize() const;
-    AddrRangeList getAddrRanges();
-    virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1);
-    void virtual init();
-    unsigned int drain(Event *de);
+    /**
+     * Create a physical memory object, wrapping a number of memories.
+     */
+    PhysicalMemory(const std::vector<AbstractMemory*>& _memories);
 
-    Tick doAtomicAccess(PacketPtr pkt);
-    void doFunctionalAccess(PacketPtr pkt);
+    /**
+     * Nothing to destruct.
+     */
+    ~PhysicalMemory() { }
+
+    /**
+     * Check if a physical address is within a range of a memory that
+     * is part of the global address map.
+     *
+     * @param addr A physical address
+     * @return Whether the address corresponds to a memory
+     */
+    bool isMemAddr(Addr addr) const;
 
+    /**
+     * Get the memory ranges for all memories that are to be reported
+     * to the configuration table.
+     *
+     * @return All configuration table memory ranges
+     */
+    AddrRangeList getConfAddrRanges() const;
 
-  protected:
-    virtual Tick calculateLatency(PacketPtr pkt);
+    /**
+     * Get the total physical memory size.
+     *
+     * @return The sum of all memory sizes
+     */
+    uint64_t totalSize() const { return size; }
 
-  public:
-     /**
-     * Register Statistics
+    /**
+     *
      */
-    void regStats();
+    void access(PacketPtr pkt);
+    void functionalAccess(PacketPtr pkt);
+};
+
 
-    virtual void serialize(std::ostream &os);
-    virtual void unserialize(Checkpoint *cp, const std::string &section);
 
-};
 
 #endif //__PHYSICAL_MEMORY_HH__
index 8fd68be7c7e52d2bb53fdf006bab690661f28723..0cdb919b138ac956694faf87318fcd17b6733e4f 100644 (file)
@@ -467,7 +467,7 @@ RubyPort::M5Port::recvFunctional(PacketPtr pkt)
         // The following command performs the real functional access.
         // This line should be removed once Ruby supplies the official version
         // of data.
-        ruby_port->system->physmem->doFunctionalAccess(pkt);
+        ruby_port->system->getPhysMem().functionalAccess(pkt);
     }
 
     // turn packet around to go back to requester if response expected
@@ -646,7 +646,7 @@ RubyPort::M5Port::hitCallback(PacketPtr pkt)
     DPRINTF(RubyPort, "Hit callback needs response %d\n", needsResponse);
 
     if (accessPhysMem) {
-        ruby_port->system->physmem->doAtomicAccess(pkt);
+        ruby_port->system->getPhysMem().access(pkt);
     } else if (needsResponse) {
         pkt->makeResponse();
     }
@@ -688,7 +688,7 @@ RubyPort::M5Port::getAddrRanges()
 bool
 RubyPort::M5Port::isPhysMemAddress(Addr addr)
 {
-    return ruby_port->system->isMemory(addr);
+    return ruby_port->system->isMemAddr(addr);
 }
 
 unsigned
diff --git a/src/mem/simple_mem.cc b/src/mem/simple_mem.cc
new file mode 100644 (file)
index 0000000..10e809d
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2010-2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ron Dreslinski
+ *          Ali Saidi
+ *          Andreas Hansson
+ */
+
+#include "base/random.hh"
+#include "mem/simple_mem.hh"
+
+using namespace std;
+
+SimpleMemory::SimpleMemory(const Params* p) :
+    AbstractMemory(p),
+    lat(p->latency), lat_var(p->latency_var)
+{
+    for (size_t i = 0; i < p->port_port_connection_count; ++i) {
+        ports.push_back(new MemoryPort(csprintf("%s-port-%d", name(), i),
+                                       *this));
+    }
+}
+
+void
+SimpleMemory::init()
+{
+    for (vector<MemoryPort*>::iterator p = ports.begin(); p != ports.end();
+         ++p) {
+        if (!(*p)->isConnected()) {
+            fatal("SimpleMemory port %s is unconnected!\n", (*p)->name());
+        } else {
+            (*p)->sendRangeChange();
+        }
+    }
+}
+
+Tick
+SimpleMemory::calculateLatency(PacketPtr pkt)
+{
+    if (pkt->memInhibitAsserted()) {
+        return 0;
+    } else {
+        Tick latency = lat;
+        if (lat_var != 0)
+            latency += random_mt.random<Tick>(0, lat_var);
+        return latency;
+    }
+}
+
+Tick
+SimpleMemory::doAtomicAccess(PacketPtr pkt)
+{
+    access(pkt);
+    return calculateLatency(pkt);
+}
+
+void
+SimpleMemory::doFunctionalAccess(PacketPtr pkt)
+{
+    functionalAccess(pkt);
+}
+
+SlavePort &
+SimpleMemory::getSlavePort(const std::string &if_name, int idx)
+{
+    if (if_name != "port") {
+        return MemObject::getSlavePort(if_name, idx);
+    } else {
+        if (idx >= static_cast<int>(ports.size())) {
+            fatal("SimpleMemory::getSlavePort: unknown index %d\n", idx);
+        }
+
+        return *ports[idx];
+    }
+}
+
+unsigned int
+SimpleMemory::drain(Event *de)
+{
+    int count = 0;
+    for (vector<MemoryPort*>::iterator p = ports.begin(); p != ports.end();
+         ++p) {
+        count += (*p)->drain(de);
+    }
+
+    if (count)
+        changeState(Draining);
+    else
+        changeState(Drained);
+    return count;
+}
+
+SimpleMemory::MemoryPort::MemoryPort(const std::string& _name,
+                                     SimpleMemory& _memory)
+    : SimpleTimingPort(_name, &_memory), memory(_memory)
+{ }
+
+AddrRangeList
+SimpleMemory::MemoryPort::getAddrRanges()
+{
+    AddrRangeList ranges;
+    ranges.push_back(memory.getAddrRange());
+    return ranges;
+}
+
+Tick
+SimpleMemory::MemoryPort::recvAtomic(PacketPtr pkt)
+{
+    return memory.doAtomicAccess(pkt);
+}
+
+void
+SimpleMemory::MemoryPort::recvFunctional(PacketPtr pkt)
+{
+    pkt->pushLabel(memory.name());
+
+    if (!queue.checkFunctional(pkt)) {
+        // Default implementation of SimpleTimingPort::recvFunctional()
+        // calls recvAtomic() and throws away the latency; we can save a
+        // little here by just not calculating the latency.
+        memory.doFunctionalAccess(pkt);
+    }
+
+    pkt->popLabel();
+}
+
+SimpleMemory*
+SimpleMemoryParams::create()
+{
+    return new SimpleMemory(this);
+}
diff --git a/src/mem/simple_mem.hh b/src/mem/simple_mem.hh
new file mode 100644 (file)
index 0000000..b21b38f
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ron Dreslinski
+ *          Andreas Hansson
+ */
+
+/**
+ * @file
+ * SimpleMemory declaration
+ */
+
+#ifndef __SIMPLE_MEMORY_HH__
+#define __SIMPLE_MEMORY_HH__
+
+#include "mem/abstract_mem.hh"
+#include "mem/tport.hh"
+#include "params/SimpleMemory.hh"
+
+/**
+ * The simple memory is a basic multi-ported memory with an infinite
+ * throughput and a fixed latency, potentially with a variance added
+ * to it. It uses a SimpleTimingPort to implement the timing accesses.
+ */
+class SimpleMemory : public AbstractMemory
+{
+
+  private:
+
+    class MemoryPort : public SimpleTimingPort
+    {
+        SimpleMemory& memory;
+
+      public:
+
+        MemoryPort(const std::string& _name, SimpleMemory& _memory);
+
+      protected:
+
+        virtual Tick recvAtomic(PacketPtr pkt);
+
+        virtual void recvFunctional(PacketPtr pkt);
+
+        virtual AddrRangeList getAddrRanges();
+
+    };
+
+    std::vector<MemoryPort*> ports;
+
+    Tick lat;
+    Tick lat_var;
+
+  public:
+
+    typedef SimpleMemoryParams Params;
+    SimpleMemory(const Params *p);
+    virtual ~SimpleMemory() { }
+
+    unsigned int drain(Event* de);
+
+    virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
+    virtual void init();
+
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+
+  protected:
+
+    Tick doAtomicAccess(PacketPtr pkt);
+    void doFunctionalAccess(PacketPtr pkt);
+    virtual Tick calculateLatency(PacketPtr pkt);
+
+};
+
+#endif //__SIMPLE_MEMORY_HH__
index 88485fcf8aa0e0c6138865ef1aaf167d5c4f0c83..f680e64bf566fa640e3c140fa3aab1dc32baf512 100644 (file)
@@ -33,7 +33,7 @@ from m5.defines import buildEnv
 from m5.params import *
 from m5.proxy import *
 
-from PhysicalMemory import *
+from SimpleMemory import *
 
 class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing']
 
@@ -52,9 +52,9 @@ class System(MemObject):
       void setMemoryMode(Enums::MemoryMode mode);
 ''')
 
-    physmem = Param.PhysicalMemory("Physical Memory")
+    memories = VectorParam.AbstractMemory(Self.all,
+                                          "All memories in the system")
     mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
-    memories = VectorParam.PhysicalMemory(Self.all, "All memories is the system")
     work_item_id = Param.Int(-1, "specific work item id")
     num_work_ids = Param.Int(16, "Number of distinct work item types")
     work_begin_cpu_id_exit = Param.Int(-1,
index 2c5d4e44b29ffa8fe3438b4422727a8a2198c991..40f5ea0ced10d697cedee042a057a72d6266479f 100644 (file)
@@ -73,7 +73,6 @@ int System::numSystemsRunning = 0;
 
 System::System(Params *p)
     : MemObject(p), _systemPort("system_port", this),
-      physmem(p->physmem),
       _numContexts(0),
       pagePtr(0),
       init_param(p->init_param),
@@ -81,6 +80,7 @@ System::System(Params *p)
       virtProxy(_systemPort),
       loadAddrMask(p->load_addr_mask),
       nextPID(0),
+      physmem(p->memories),
       memoryMode(p->mem_mode),
       workItemsBegin(0),
       workItemsEnd(0),
@@ -92,16 +92,6 @@ System::System(Params *p)
     // add self to global system list
     systemList.push_back(this);
 
-    /** Keep track of all memories we can execute code out of
-     * in our system
-     */
-    for (int x = 0; x < p->memories.size(); x++) {
-        if (!p->memories[x])
-            continue;
-        memRanges.push_back(RangeSize(p->memories[x]->start(),
-                                      p->memories[x]->size()));
-    }
-
     if (FullSystem) {
         kernelSymtab = new SymbolTable;
         if (!debugSymbolTable)
@@ -308,32 +298,27 @@ System::allocPhysPages(int npages)
 {
     Addr return_addr = pagePtr << LogVMPageSize;
     pagePtr += npages;
-    if (pagePtr > physmem->size())
+    if (pagePtr > physmem.totalSize())
         fatal("Out of memory, please increase size of physical memory.");
     return return_addr;
 }
 
 Addr
-System::memSize()
+System::memSize() const
 {
-    return physmem->size();
+    return physmem.totalSize();
 }
 
 Addr
-System::freeMemSize()
+System::freeMemSize() const
 {
-   return physmem->size() - (pagePtr << LogVMPageSize);
+   return physmem.totalSize() - (pagePtr << LogVMPageSize);
 }
 
 bool
-System::isMemory(const Addr addr) const
+System::isMemAddr(Addr addr) const
 {
-    std::list<Range<Addr> >::const_iterator i;
-    for (i = memRanges.begin(); i != memRanges.end(); i++) {
-        if (*i == addr)
-            return true;
-    }
-    return false;
+    return physmem.isMemAddr(addr);
 }
 
 void
index d5e45fa0d92f866fc8ae4ef056a919b5744746fa..7b5ba998ebda8ef2c884456e36adc03a58f3dc82 100644 (file)
 #include "mem/fs_translating_port_proxy.hh"
 #include "mem/mem_object.hh"
 #include "mem/port.hh"
+#include "mem/physical.hh"
 #include "params/System.hh"
 
 class BaseCPU;
 class BaseRemoteGDB;
 class GDBListener;
 class ObjectFile;
-class PhysicalMemory;
 class Platform;
 class ThreadContext;
 
@@ -138,7 +138,6 @@ class System : public MemObject
      */
     void setMemoryMode(Enums::MemoryMode mode);
 
-    PhysicalMemory *physmem;
     PCEventQueue pcEventQueue;
 
     std::vector<ThreadContext *> threadContexts;
@@ -159,14 +158,6 @@ class System : public MemObject
      * system.  These threads could be Active or Suspended. */
     int numRunningContexts();
 
-    /** List to store ranges of memories in this system */
-    AddrRangeList memRanges;
-
-    /** check if an address points to valid system memory
-     * and thus we can fetch instructions out of it
-     */
-    bool isMemory(const Addr addr) const;
-
     Addr pagePtr;
 
     uint64_t init_param;
@@ -208,13 +199,28 @@ class System : public MemObject
         return nextPID++;
     }
 
+    /** Get a pointer to access the physical memory of the system */
+    PhysicalMemory& getPhysMem() { return physmem; }
+
     /** Amount of physical memory that is still free */
-    Addr freeMemSize();
+    Addr freeMemSize() const;
 
     /** Amount of physical memory that exists */
-    Addr memSize();
+    Addr memSize() const;
+
+    /**
+     * Check if a physical address is within a range of a memory that
+     * is part of the global address map.
+     *
+     * @param addr A physical address
+     * @return Whether the address corresponds to a memory
+     */
+    bool isMemAddr(Addr addr) const;
 
   protected:
+
+    PhysicalMemory physmem;
+
     Enums::MemoryMode memoryMode;
     uint64_t workItemsBegin;
     uint64_t workItemsEnd;
index d6a456083ca707ffe0cd66973e649b7dc91bd3c9..ea9c37ef94dcdcb5e6c4ff70602105643256a91f 100644 (file)
@@ -48,7 +48,7 @@ cpu.addTwoLevelCacheHierarchy(MyL1Cache(size = '128kB'),
 cpu.clock = '2GHz'
 
 system = System(cpu = cpu,
-                physmem = PhysicalMemory(),
+                physmem = SimpleMemory(),
                 membus = Bus())
 system.system_port = system.membus.slave
 system.physmem.port = system.membus.master
index c69e1bf00d49c8e3436582fc5a24404c312c7431..e668ef9ba34cc09f343082bd249623ae2fc6f2b8 100644 (file)
@@ -77,8 +77,8 @@ options.num_cpus = nb_cores
  
 # system simulated
 system = System(cpu = cpus,
-                funcmem = PhysicalMemory(),
-                physmem = PhysicalMemory())
+                funcmem = SimpleMemory(in_addr_map = False),
+                physmem = SimpleMemory())
 
 Ruby.create_system(options, system)
 
index 6fface748bb99949e8beb639ff4fad94a3147ad2..9876c07b9ad98da181917960c3af47a2d49ae753 100644 (file)
@@ -56,8 +56,8 @@ nb_cores = 8
 cpus = [ MemTest() for i in xrange(nb_cores) ]
 
 # system simulated
-system = System(cpu = cpus, funcmem = PhysicalMemory(),
-                physmem = PhysicalMemory(),
+system = System(cpu = cpus, funcmem = SimpleMemory(in_addr_map = False),
+                physmem = SimpleMemory(),
                 membus = Bus(clock="500GHz", width=16))
 
 # l2cache & bus
index dd68a39d785305f09c4b6830974ef6e8f5b1766c..68429de04c8bd71b5defae1b234e037287c6ef5d 100644 (file)
@@ -59,7 +59,7 @@ cpu.addTwoLevelCacheHierarchy(MyL1Cache(size = '128kB'),
 cpu.clock = '2GHz'
 
 system = System(cpu = cpu,
-                physmem = PhysicalMemory(),
+                physmem = SimpleMemory(),
                 membus = Bus())
 system.system_port = system.membus.slave
 system.physmem.port = system.membus.master
index 1a0718fa8d88ac1730c11b79be3d9f53a5061c9d..ee0f29570cc9283ca3c81f7eea1d6cc6cf987701 100644 (file)
@@ -56,8 +56,7 @@ nb_cores = 4
 cpus = [ DerivO3CPU(cpu_id=i) for i in xrange(nb_cores) ]
 
 # system simulated
-system = System(cpu = cpus, physmem = PhysicalMemory(), membus =
-Bus())
+system = System(cpu = cpus, physmem = SimpleMemory(), membus = Bus())
 
 # l2cache & bus
 system.toL2Bus = Bus()
index 82a73a6aa40df865edd7eda7d84e99b4c633b5d7..732cd2d439c0e7e98099f659246f77ee770c861d 100644 (file)
@@ -48,7 +48,7 @@ cpu.addTwoLevelCacheHierarchy(MyL1Cache(size = '128kB'),
 cpu.clock = '2GHz'
 
 system = System(cpu = cpu,
-                physmem = PhysicalMemory(),
+                physmem = SimpleMemory(),
                 membus = Bus())
 system.system_port = system.membus.slave
 system.physmem.port = system.membus.master
index 70deb2958fa2e30580dbc9894cc6b92914cf2a4d..7bb7b90145b1adf7804d9e75d13813f4f15a6dc8 100644 (file)
@@ -70,7 +70,7 @@ options.l3_assoc=2
 #
 tester = RubyTester(checks_to_complete = 100, wakeup_frequency = 10)
 
-system = System(tester = tester, physmem = PhysicalMemory())
+system = System(tester = tester, physmem = SimpleMemory())
 
 Ruby.create_system(options, system)
 
index 15c2871302eca429aa95eeebf8184c66d6829a26..2e672924d67ed1f4c8c7ece1eed69cb6c144d650 100644 (file)
@@ -39,7 +39,7 @@ import m5
 from m5.objects import *
 
 system = System(cpu = AtomicSimpleCPU(cpu_id=0),
-                physmem = PhysicalMemory(),
+                physmem = SimpleMemory(),
                 membus = Bus())
 system.system_port = system.membus.slave
 system.physmem.port = system.membus.master
index 376d5ee27541ee8f4310f816d49a582cb5db23f2..af9f3bc09a1c821033bc484e27618d7cc8ab4a92 100644 (file)
@@ -55,8 +55,9 @@ nb_cores = 4
 cpus = [ AtomicSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ]
 
 # system simulated
-system = System(cpu = cpus, physmem = PhysicalMemory(range = AddrRange('1024MB')), membus =
-Bus())
+system = System(cpu = cpus,
+                physmem = SimpleMemory(range = AddrRange('1024MB')),
+                membus = Bus())
 
 # l2cache & bus
 system.toL2Bus = Bus()
index 4d3fb65805f300f4ab317eb9ca22481cfc6a3581..b1aa31d8024c9aeb0dbf453e98fee04caab14e58 100644 (file)
@@ -30,7 +30,7 @@ import m5
 from m5.objects import *
 
 system = System(cpu = AtomicSimpleCPU(cpu_id=0),
-                physmem = PhysicalMemory(),
+                physmem = SimpleMemory(),
                 membus = Bus())
 system.system_port = system.membus.slave
 system.physmem.port = system.membus.master
index d2f11abce5452cea7451c3931af0afbd6c558f6d..4447967a7ebe22068b5f64b8c126b6bb74b2dc09 100644 (file)
@@ -70,7 +70,7 @@ cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ]
 options.num_cpus = nb_cores
 
 # system simulated
-system = System(cpu = cpus, physmem = PhysicalMemory())
+system = System(cpu = cpus, physmem = SimpleMemory())
 
 Ruby.create_system(options, system)
 
index f898797bb22b1552a47519e4a17d2c600e5f5737..5bb0194aa99513b6a6651a987af701d343644a93 100644 (file)
@@ -55,8 +55,7 @@ nb_cores = 4
 cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ]
 
 # system simulated
-system = System(cpu = cpus, physmem = PhysicalMemory(), membus =
-Bus())
+system = System(cpu = cpus, physmem = SimpleMemory(), membus = Bus())
 
 # l2cache & bus
 system.toL2Bus = Bus()
index 19e827c806084a5176db0e7de44a7f66f33aeb2f..1a983510a4785e8eeb725393430bad72fe0e7a8b 100644 (file)
@@ -66,7 +66,7 @@ options.l3_assoc=2
 options.num_cpus = 1
 
 cpu = TimingSimpleCPU(cpu_id=0)
-system = System(cpu = cpu, physmem = PhysicalMemory())
+system = System(cpu = cpu, physmem = SimpleMemory())
 
 Ruby.create_system(options, system)
 
index cd6bee863c28b481564482360cd179893ecd1652..5269f41275284d332e08025c4eea8f875a34ddad 100644 (file)
@@ -44,7 +44,7 @@ cpu.addTwoLevelCacheHierarchy(MyL1Cache(size = '128kB'),
                               MyL1Cache(size = '256kB'),
                               MyCache(size = '2MB', latency='10ns'))
 system = System(cpu = cpu,
-                physmem = PhysicalMemory(),
+                physmem = SimpleMemory(),
                 membus = Bus())
 system.system_port = system.membus.slave
 system.physmem.port = system.membus.master