summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConscript87
-rw-r--r--arch/alpha/isa/main.isa2
-rw-r--r--arch/alpha/linux/process.hh1
-rw-r--r--arch/alpha/tru64/process.hh1
-rw-r--r--base/chunk_generator.hh137
-rw-r--r--base/intmath.hh4
-rw-r--r--base/loader/aout_object.cc26
-rw-r--r--base/loader/aout_object.hh2
-rw-r--r--base/loader/ecoff_object.cc25
-rw-r--r--base/loader/ecoff_object.hh2
-rw-r--r--base/loader/elf_object.cc31
-rw-r--r--base/loader/elf_object.hh5
-rw-r--r--base/loader/object_file.cc34
-rw-r--r--base/loader/object_file.hh12
-rw-r--r--configs/test.py8
-rw-r--r--cpu/base.cc3
-rw-r--r--cpu/base.hh8
-rw-r--r--cpu/cpu_exec_context.cc18
-rw-r--r--cpu/cpu_exec_context.hh72
-rw-r--r--cpu/exetrace.cc3
-rw-r--r--cpu/op_class.cc50
-rw-r--r--cpu/op_class.hh (renamed from encumbered/cpu/full/op_class.hh)38
-rw-r--r--cpu/pc_event.hh5
-rw-r--r--cpu/simple/cpu.cc399
-rw-r--r--cpu/simple/cpu.hh107
-rw-r--r--cpu/static_inst.hh2
-rw-r--r--dev/io_device.cc111
-rw-r--r--dev/io_device.hh147
-rw-r--r--dev/platform.hh4
-rw-r--r--mem/bus.hh128
-rw-r--r--mem/mem_object.hh56
-rw-r--r--mem/packet.hh125
-rw-r--r--mem/page_table.cc129
-rw-r--r--mem/page_table.hh89
-rw-r--r--mem/physical.cc378
-rw-r--r--mem/physical.hh143
-rw-r--r--mem/port.cc76
-rw-r--r--mem/port.hh227
-rw-r--r--mem/request.hh107
-rw-r--r--mem/translating_port.cc149
-rw-r--r--mem/translating_port.hh61
-rw-r--r--python/m5/objects/BaseCPU.py4
-rw-r--r--python/m5/objects/Ethernet.py1
-rw-r--r--python/m5/objects/MemObject.py5
-rw-r--r--python/m5/objects/PhysicalMemory.py7
-rw-r--r--python/m5/objects/Process.py1
-rw-r--r--python/m5/objects/Root.py4
-rw-r--r--sim/process.cc110
-rw-r--r--sim/process.hh40
-rw-r--r--sim/syscall_emul.cc16
-rw-r--r--sim/syscall_emul.hh64
-rw-r--r--sim/system.cc56
-rw-r--r--sim/system.hh45
53 files changed, 2876 insertions, 489 deletions
diff --git a/SConscript b/SConscript
index 8afac510b..3a141a7d2 100644
--- a/SConscript
+++ b/SConscript
@@ -81,67 +81,18 @@ base_sources = Split('''
base/stats/text.cc
cpu/base.cc
- cpu/base_dyn_inst.cc
cpu/cpu_exec_context.cc
cpu/exetrace.cc
+ cpu/op_class.cc
cpu/pc_event.cc
cpu/static_inst.cc
cpu/sampler/sampler.cc
- cpu/trace/reader/mem_trace_reader.cc
- cpu/trace/reader/ibm_reader.cc
- cpu/trace/reader/itx_reader.cc
- cpu/trace/reader/m5_reader.cc
- cpu/trace/opt_cpu.cc
- cpu/trace/trace_cpu.cc
- encumbered/mem/functional/main.cc
-
- mem/base_hier.cc
- mem/base_mem.cc
- mem/hier_params.cc
- mem/mem_cmd.cc
- mem/mem_debug.cc
- mem/mem_req.cc
- mem/memory_interface.cc
- mem/bus/base_interface.cc
- mem/bus/bus.cc
- mem/bus/bus_bridge.cc
- mem/bus/bus_bridge_master.cc
- mem/bus/bus_bridge_slave.cc
- mem/bus/bus_interface.cc
- mem/bus/dma_bus_interface.cc
- mem/bus/dma_interface.cc
- mem/bus/master_interface.cc
- mem/bus/slave_interface.cc
- mem/cache/base_cache.cc
- mem/cache/cache.cc
- mem/cache/cache_builder.cc
- mem/cache/coherence/coherence_protocol.cc
- mem/cache/coherence/uni_coherence.cc
- mem/cache/miss/blocking_buffer.cc
- mem/cache/miss/miss_queue.cc
- mem/cache/miss/mshr.cc
- mem/cache/miss/mshr_queue.cc
- mem/cache/prefetch/base_prefetcher.cc
- mem/cache/prefetch/prefetcher.cc
- mem/cache/prefetch/tagged_prefetcher.cc
- mem/cache/tags/base_tags.cc
- mem/cache/tags/cache_tags.cc
- mem/cache/tags/fa_lru.cc
- mem/cache/tags/iic.cc
- mem/cache/tags/lru.cc
- mem/cache/tags/repl/gen.cc
- mem/cache/tags/repl/repl.cc
- mem/cache/tags/split.cc
- mem/cache/tags/split_lru.cc
- mem/cache/tags/split_lifo.cc
- mem/functional/functional.cc
- mem/timing/base_memory.cc
- mem/timing/memory_builder.cc
- mem/timing/simple_mem_bank.cc
- mem/trace/itx_writer.cc
- mem/trace/mem_trace_writer.cc
- mem/trace/m5_writer.cc
+ mem/memory.cc
+ mem/page_table.cc
+ mem/physical.cc
+ mem/port.cc
+ mem/translating_port.cc
python/pyconfig.cc
python/embedded_py.cc
@@ -162,6 +113,7 @@ base_sources = Split('''
sim/startup.cc
sim/stat_context.cc
sim/stat_control.cc
+ sim/system.cc
sim/trace_context.cc
''')
@@ -204,6 +156,17 @@ full_cpu_sources = Split('''
encumbered/cpu/full/iq/standard/iq_standard.cc
''')
+trace_reader_sources = Split('''
+ cpu/trace/reader/mem_trace_reader.cc
+ cpu/trace/reader/ibm_reader.cc
+ cpu/trace/reader/itx_reader.cc
+ cpu/trace/reader/m5_reader.cc
+ cpu/trace/opt_cpu.cc
+ cpu/trace/trace_cpu.cc
+ ''')
+
+
+
# MySql sources
mysql_sources = Split('''
base/mysql.cc
@@ -260,9 +223,6 @@ full_system_sources = Split('''
kern/tru64/tru64_syscalls.cc
mem/functional/memory_control.cc
- mem/functional/physical.cc
-
- sim/system.cc
sim/pseudo_inst.cc
''')
@@ -288,8 +248,7 @@ turbolaser_sources = Split('''
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
- cpu/memtest/memtest.cc
- encumbered/eio/eio.cc
+
encumbered/eio/exolex.cc
encumbered/eio/libexo.cc
kern/linux/linux.cc
@@ -298,6 +257,14 @@ syscall_emulation_sources = Split('''
sim/syscall_emul.cc
''')
+eio_sources = Split('''
+ encumbered/eio/eio.cc
+ ''')
+
+memtest_sources = Split('''
+ cpu/memtest/memtest.cc
+ ''')
+
# Add a flag defining what THE_ISA should be for all compilation
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa
index 17c9989ab..d4c744fbc 100644
--- a/arch/alpha/isa/main.isa
+++ b/arch/alpha/isa/main.isa
@@ -34,7 +34,7 @@ output header {{
#include "config/ss_compatible_fp.hh"
#include "cpu/static_inst.hh"
#include "arch/alpha/faults.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
+#include "mem/request.hh" // some constructors use MemReq flags
}};
output decoder {{
diff --git a/arch/alpha/linux/process.hh b/arch/alpha/linux/process.hh
index 7de1b1ac1..2cabc3f76 100644
--- a/arch/alpha/linux/process.hh
+++ b/arch/alpha/linux/process.hh
@@ -39,6 +39,7 @@ class AlphaLinuxProcess : public LiveProcess
/// Constructor.
AlphaLinuxProcess(const std::string &name,
ObjectFile *objFile,
+ System *system,
int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
diff --git a/arch/alpha/tru64/process.hh b/arch/alpha/tru64/process.hh
index 051760702..84abd54bf 100644
--- a/arch/alpha/tru64/process.hh
+++ b/arch/alpha/tru64/process.hh
@@ -38,6 +38,7 @@ class AlphaTru64Process : public LiveProcess
/// Constructor.
AlphaTru64Process(const std::string &name,
ObjectFile *objFile,
+ System *system,
int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
diff --git a/base/chunk_generator.hh b/base/chunk_generator.hh
new file mode 100644
index 000000000..a584679d0
--- /dev/null
+++ b/base/chunk_generator.hh
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#ifndef __BASE__CHUNK_GENERATOR_HH__
+#define __BASE__CHUNK_GENERATOR_HH__
+
+/**
+ * @file
+ * Declaration and inline definition of ChunkGenerator object.
+ */
+
+#include <algorithm>
+#include "base/intmath.hh"
+#include "targetarch/isa_traits.hh" // for Addr
+
+/**
+ * This class takes an arbitrary memory region (address/length pair)
+ * and generates a series of appropriately (e.g. block- or page-)
+ * aligned chunks covering the same region.
+ *
+ * Example usage:
+
+\code
+ for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
+ doSomethingChunky(gen.addr(), gen.size());
+ }
+\endcode
+ */
+class ChunkGenerator
+{
+ private:
+ /** The starting address of the current chunk. */
+ Addr curAddr;
+ /** The starting address of the next chunk (after the current one). */
+ Addr nextAddr;
+ /** The size of the current chunk (in bytes). */
+ int curSize;
+ /** The number of bytes remaining in the region after the current chunk. */
+ int sizeLeft;
+ /** The maximum chunk size, e.g., the cache block size or page size. */
+ const int chunkSize;
+
+ public:
+ /**
+ * Constructor.
+ * @param startAddr The starting address of the region.
+ * @param totalSize The total size of the region.
+ * @param _chunkSize The size/alignment of chunks into which
+ * the region should be decomposed.
+ */
+ ChunkGenerator(Addr startAddr, int totalSize, int _chunkSize)
+ : chunkSize(_chunkSize)
+ {
+ // chunkSize must be a power of two
+ assert(chunkSize == 0 || isPowerOf2(chunkSize));
+
+ // set up initial chunk.
+ curAddr = startAddr;
+
+ if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
+ {
+ nextAddr = startAddr + totalSize;
+ }
+ else
+ {
+ // nextAddr should be *next* chunk start
+ nextAddr = roundUp(startAddr, chunkSize);
+ if (curAddr == nextAddr) {
+ // ... even if startAddr is already chunk-aligned
+ nextAddr += chunkSize;
+ }
+ }
+
+ // how many bytes are left between curAddr and the end of this chunk?
+ int left_in_chunk = nextAddr - curAddr;
+ curSize = std::min(totalSize, left_in_chunk);
+ sizeLeft = totalSize - curSize;
+ }
+
+ /** Return starting address of current chunk. */
+ Addr addr() { return curAddr; }
+ /** Return size in bytes of current chunk. */
+ int size() { return curSize; }
+
+ /**
+ * Are we done? That is, did the last call to next() advance
+ * past the end of the region?
+ * @return True if yes, false if more to go.
+ */
+ bool done() { return (curSize == 0); }
+
+ /**
+ * Advance generator to next chunk.
+ * @return True if successful, false if unsuccessful
+ * (because we were at the last chunk).
+ */
+ bool next()
+ {
+ if (sizeLeft == 0) {
+ curSize = 0;
+ return false;
+ }
+
+ curAddr = nextAddr;
+ curSize = std::min(sizeLeft, chunkSize);
+ sizeLeft -= curSize;
+ nextAddr += curSize;
+ return true;
+ }
+};
+
+#endif // __BASE__CHUNK_GENERATOR_HH__
diff --git a/base/intmath.hh b/base/intmath.hh
index df0687c62..51baddb91 100644
--- a/base/intmath.hh
+++ b/base/intmath.hh
@@ -186,9 +186,9 @@ roundUp(T val, int align)
template <class T>
inline T
-roundDown(T val, T align)
+roundDown(T val, int align)
{
- T mask = align - 1;
+ T mask = (T)align - 1;
return val & ~mask;
}
diff --git a/base/loader/aout_object.cc b/base/loader/aout_object.cc
index c81f7123f..564898ca3 100644
--- a/base/loader/aout_object.cc
+++ b/base/loader/aout_object.cc
@@ -30,7 +30,6 @@
#include "base/loader/aout_object.hh"
-#include "mem/functional/functional.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh" // for DPRINTF
@@ -64,12 +63,15 @@ AoutObject::AoutObject(const string &_filename, int _fd,
text.baseAddr = N_TXTADDR(*execHdr);
text.size = execHdr->tsize;
+ text.fileImage = fileData + N_TXTOFF(*execHdr);
data.baseAddr = N_DATADDR(*execHdr);
data.size = execHdr->dsize;
+ data.fileImage = fileData + N_DATOFF(*execHdr);
bss.baseAddr = N_BSSADDR(*execHdr);
bss.size = execHdr->bsize;
+ bss.fileImage = NULL;
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
@@ -78,28 +80,6 @@ AoutObject::AoutObject(const string &_filename, int _fd,
bool
-AoutObject::loadSections(FunctionalMemory *mem, bool loadPhys)
-{
- Addr textAddr = text.baseAddr;
- Addr dataAddr = data.baseAddr;
-
- if (loadPhys) {
- textAddr &= (ULL(1) << 40) - 1;
- dataAddr &= (ULL(1) << 40) - 1;
- }
-
- // Since we don't really have an MMU and all memory is
- // zero-filled, there's no need to set up the BSS segment.
- if (text.size != 0)
- mem->prot_write(textAddr, fileData + N_TXTOFF(*execHdr), text.size);
- if (data.size != 0)
- mem->prot_write(dataAddr, fileData + N_DATOFF(*execHdr), data.size);
-
- return true;
-}
-
-
-bool
AoutObject::loadGlobalSymbols(SymbolTable *symtab)
{
// a.out symbols not supported yet
diff --git a/base/loader/aout_object.hh b/base/loader/aout_object.hh
index 1868192b2..aeb710427 100644
--- a/base/loader/aout_object.hh
+++ b/base/loader/aout_object.hh
@@ -46,8 +46,6 @@ class AoutObject : public ObjectFile
public:
virtual ~AoutObject() {}
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab);
virtual bool loadLocalSymbols(SymbolTable *symtab);
diff --git a/base/loader/ecoff_object.cc b/base/loader/ecoff_object.cc
index 353a5f333..cd37abaa7 100644
--- a/base/loader/ecoff_object.cc
+++ b/base/loader/ecoff_object.cc
@@ -29,8 +29,6 @@
#include <string>
#include "base/loader/ecoff_object.hh"
-
-#include "mem/functional/functional.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh" // for DPRINTF
@@ -68,12 +66,15 @@ EcoffObject::EcoffObject(const string &_filename, int _fd,
text.baseAddr = aoutHdr->text_start;
text.size = aoutHdr->tsize;
+ text.fileImage = fileData + ECOFF_TXTOFF(execHdr);
data.baseAddr = aoutHdr->data_start;
data.size = aoutHdr->dsize;
+ data.fileImage = fileData + ECOFF_DATOFF(execHdr);
bss.baseAddr = aoutHdr->bss_start;
bss.size = aoutHdr->bsize;
+ bss.fileImage = NULL;
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
@@ -82,26 +83,6 @@ EcoffObject::EcoffObject(const string &_filename, int _fd,
bool
-EcoffObject::loadSections(FunctionalMemory *mem, bool loadPhys)
-{
- Addr textAddr = text.baseAddr;
- Addr dataAddr = data.baseAddr;
-
- if (loadPhys) {
- textAddr &= (ULL(1) << 40) - 1;
- dataAddr &= (ULL(1) << 40) - 1;
- }
-
- // Since we don't really have an MMU and all memory is
- // zero-filled, there's no need to set up the BSS segment.
- mem->prot_write(textAddr, fileData + ECOFF_TXTOFF(execHdr), text.size);
- mem->prot_write(dataAddr, fileData + ECOFF_DATOFF(execHdr), data.size);
-
- return true;
-}
-
-
-bool
EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
{
if (!symtab)
diff --git a/base/loader/ecoff_object.hh b/base/loader/ecoff_object.hh
index 78aa7f3f7..603c70bec 100644
--- a/base/loader/ecoff_object.hh
+++ b/base/loader/ecoff_object.hh
@@ -50,8 +50,6 @@ class EcoffObject : public ObjectFile
public:
virtual ~EcoffObject() {}
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab);
virtual bool loadLocalSymbols(SymbolTable *symtab);
diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc
index 791c6f6de..1136686f0 100644
--- a/base/loader/elf_object.cc
+++ b/base/loader/elf_object.cc
@@ -43,7 +43,6 @@
#include "base/loader/elf_object.hh"
-#include "mem/functional/functional.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh" // for DPRINTF
@@ -203,20 +202,19 @@ ElfObject::ElfObject(const string &_filename, int _fd,
if (text.size == 0) { // haven't seen text segment yet
text.baseAddr = phdr.p_vaddr;
text.size = phdr.p_filesz;
- // remember where the data is for loadSections()
- fileTextBits = fileData + phdr.p_offset;
+ text.fileImage = fileData + phdr.p_offset;
// if there's any padding at the end that's not in the
// file, call it the bss. This happens in the "text"
// segment if there's only one loadable segment (as for
// kernel images).
bss.size = phdr.p_memsz - phdr.p_filesz;
bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
+ bss.fileImage = NULL;
}
else if (data.size == 0) { // have text, this must be data
data.baseAddr = phdr.p_vaddr;
data.size = phdr.p_filesz;
- // remember where the data is for loadSections()
- fileDataBits = fileData + phdr.p_offset;
+ data.fileImage = fileData + phdr.p_offset;
// if there's any padding at the end that's not in the
// file, call it the bss. Warn if this happens for both
// the text & data segments (should only have one bss).
@@ -225,6 +223,7 @@ ElfObject::ElfObject(const string &_filename, int _fd,
}
bss.size = phdr.p_memsz - phdr.p_filesz;
bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
+ bss.fileImage = NULL;
}
}
@@ -242,28 +241,6 @@ ElfObject::ElfObject(const string &_filename, int _fd,
bool
-ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys)
-{
- Addr textAddr = text.baseAddr;
- Addr dataAddr = data.baseAddr;
-
- if (loadPhys) {
- textAddr &= (ULL(1) << 40) - 1;
- dataAddr &= (ULL(1) << 40) - 1;
- }
-
- // Since we don't really have an MMU and all memory is
- // zero-filled, there's no need to set up the BSS segment.
- if (text.size != 0)
- mem->prot_write(textAddr, fileTextBits, text.size);
- if (data.size != 0)
- mem->prot_write(dataAddr, fileDataBits, data.size);
-
- return true;
-}
-
-
-bool
ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding)
{
Elf *elf;
diff --git a/base/loader/elf_object.hh b/base/loader/elf_object.hh
index 66d8b3e63..72c265edd 100644
--- a/base/loader/elf_object.hh
+++ b/base/loader/elf_object.hh
@@ -35,9 +35,6 @@ class ElfObject : public ObjectFile
{
protected:
- uint8_t *fileTextBits; //!< Pointer to file's text segment image
- uint8_t *fileDataBits; //!< Pointer to file's data segment image
-
/// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
bool loadSomeSymbols(SymbolTable *symtab, int binding);
@@ -48,8 +45,6 @@ class ElfObject : public ObjectFile
public:
virtual ~ElfObject() {}
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab);
virtual bool loadLocalSymbols(SymbolTable *symtab);
diff --git a/base/loader/object_file.cc b/base/loader/object_file.cc
index 1410d05b8..f33957269 100644
--- a/base/loader/object_file.cc
+++ b/base/loader/object_file.cc
@@ -43,6 +43,8 @@
#include "base/loader/aout_object.hh"
#include "base/loader/elf_object.hh"
+#include "mem/translating_port.hh"
+
using namespace std;
ObjectFile::ObjectFile(const string &_filename, int _fd,
@@ -60,6 +62,38 @@ ObjectFile::~ObjectFile()
}
+bool
+ObjectFile::loadSection(Section *sec, TranslatingPort *memPort, bool loadPhys)
+{
+ if (sec->size != 0) {
+ Addr addr = sec->baseAddr;
+ if (loadPhys) {
+ // this is Alpha-specific... going to have to fix this
+ // for other architectures
+ addr &= (ULL(1) << 40) - 1;
+ }
+
+ if (sec->fileImage) {
+ memPort->writeBlobFunctional(addr, sec->fileImage, sec->size, true);
+ }
+ else {
+ // no image: must be bss
+ memPort->memsetBlobFunctional(addr, 0, sec->size, true);
+ }
+ }
+ return true;
+}
+
+
+bool
+ObjectFile::loadSections(TranslatingPort *memPort, bool loadPhys)
+{
+ return (loadSection(&text, memPort, loadPhys)
+ && loadSection(&data, memPort, loadPhys)
+ && loadSection(&bss, memPort, loadPhys));
+}
+
+
void
ObjectFile::close()
{
diff --git a/base/loader/object_file.hh b/base/loader/object_file.hh
index 1b44ae14f..08a51863e 100644
--- a/base/loader/object_file.hh
+++ b/base/loader/object_file.hh
@@ -33,7 +33,7 @@
#include "sim/host.hh" // for Addr
-class FunctionalMemory;
+class TranslatingPort;
class SymbolTable;
class ObjectFile
@@ -72,8 +72,7 @@ class ObjectFile
void close();
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false) = 0;
+ virtual bool loadSections(TranslatingPort *memPort, bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
@@ -83,8 +82,9 @@ class ObjectFile
protected:
struct Section {
- Addr baseAddr;
- size_t size;
+ Addr baseAddr;
+ uint8_t *fileImage;
+ size_t size;
};
Addr entry;
@@ -94,6 +94,8 @@ class ObjectFile
Section data;
Section bss;
+ bool loadSection(Section *sec, TranslatingPort *memPort, bool loadPhys);
+
public:
Addr entryPoint() const { return entry; }
Addr globalPointer() const { return globalPtr; }
diff --git a/configs/test.py b/configs/test.py
new file mode 100644
index 000000000..ea0e63a61
--- /dev/null
+++ b/configs/test.py
@@ -0,0 +1,8 @@
+from m5 import *
+AddToPath('/z/stever/bk/m5-test')
+import Benchmarks
+
+mem = PhysicalMemory()
+cpu = SimpleCPU(workload=Benchmarks.HelloWorld(), mem=mem)
+system = System(physmem=mem, cpu=cpu)
+root = Root(system=system)
diff --git a/cpu/base.cc b/cpu/base.cc
index 2eb5f7fd3..9ce458c64 100644
--- a/cpu/base.cc
+++ b/cpu/base.cc
@@ -65,7 +65,7 @@ BaseCPU::BaseCPU(Params *p)
#else
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), params(p),
- number_of_threads(p->numberOfThreads)
+ number_of_threads(p->numberOfThreads), system(p->system)
#endif
{
DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
@@ -229,6 +229,7 @@ BaseCPU::registerExecContexts()
{
for (int i = 0; i < execContexts.size(); ++i) {
ExecContext *xc = execContexts[i];
+
#if FULL_SYSTEM
int id = params->cpu_id;
if (id != -1)
diff --git a/cpu/base.hh b/cpu/base.hh
index d9d5d2b88..0866b49a7 100644
--- a/cpu/base.hh
+++ b/cpu/base.hh
@@ -38,13 +38,11 @@
#include "sim/sim_object.hh"
#include "arch/isa_traits.hh"
-#if FULL_SYSTEM
class System;
namespace Kernel { class Statistics; }
-#endif
-
class BranchPred;
class ExecContext;
+class Port;
class BaseCPU : public SimObject
{
@@ -123,8 +121,8 @@ class BaseCPU : public SimObject
Tick clock;
bool functionTrace;
Tick functionTraceStart;
-#if FULL_SYSTEM
System *system;
+#if FULL_SYSTEM
int cpu_id;
Tick profile;
#endif
@@ -173,9 +171,9 @@ class BaseCPU : public SimObject
*/
EventQueue **comLoadEventQueue;
-#if FULL_SYSTEM
System *system;
+#if FULL_SYSTEM
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc
index b7238e73a..6ef42762d 100644
--- a/cpu/cpu_exec_context.cc
+++ b/cpu/cpu_exec_context.cc
@@ -45,6 +45,7 @@
#include "arch/stacktrace.hh"
#else
#include "sim/process.hh"
+#include "mem/translating_port.hh"
#endif
using namespace std;
@@ -53,7 +54,7 @@ using namespace std;
#if FULL_SYSTEM
CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
AlphaITB *_itb, AlphaDTB *_dtb,
- FunctionalMemory *_mem)
+ Memory *_mem)
: _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb),
dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem),
@@ -79,21 +80,13 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
}
#else
CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
- Process *_process, int _asid)
+ Process *_process, int _asid, Port *mem_port)
: _status(ExecContext::Unallocated),
cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0),
- lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid),
- func_exe_inst(0), storeCondFailures(0)
-{
- memset(&regs, 0, sizeof(RegFile));
- proxy = new ProxyExecContext<CPUExecContext>(this);
-}
-
-CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
- FunctionalMemory *_mem, int _asid)
- : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
+ lastSuspend(0), process(_process), asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
+ port = new TranslatingPort(mem_port, process->pTable);
memset(&regs, 0, sizeof(RegFile));
proxy = new ProxyExecContext<CPUExecContext>(this);
}
@@ -158,7 +151,6 @@ void
CPUExecContext::takeOverFrom(ExecContext *oldContext)
{
// some things should already be set up
- assert(mem == oldContext->getMemPtr());
#if FULL_SYSTEM
assert(system == oldContext->getSystemPtr());
#else
diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh
index beaf67352..e17cfbb94 100644
--- a/cpu/cpu_exec_context.hh
+++ b/cpu/cpu_exec_context.hh
@@ -32,16 +32,13 @@
#include "arch/isa_traits.hh"
#include "config/full_system.hh"
#include "cpu/exec_context.hh"
-#include "mem/functional/functional.hh"
-#include "mem/mem_req.hh"
+#include "mem/physical.hh"
+#include "mem/request.hh"
#include "sim/byteswap.hh"
#include "sim/eventq.hh"
#include "sim/host.hh"
#include "sim/serialize.hh"
-// forward declaration: see functional_memory.hh
-class FunctionalMemory;
-class PhysicalMemory;
class BaseCPU;
#if FULL_SYSTEM
@@ -56,6 +53,7 @@ class MemoryController;
#else // !FULL_SYSTEM
#include "sim/process.hh"
+class TranslatingPort;
#endif // FULL_SYSTEM
@@ -118,17 +116,21 @@ class CPUExecContext
Tick lastActivate;
Tick lastSuspend;
+ System *system;
+
+ /// Port that syscalls can use to access memory (provides translation step).
+ TranslatingPort *port;
+// Memory *mem;
+
#if FULL_SYSTEM
- FunctionalMemory *mem;
AlphaITB *itb;
AlphaDTB *dtb;
- System *system;
// the following two fields are redundant, since we can always
// look them up through the system pointer, but we'll leave them
// here for now for convenience
MemoryController *memctrl;
- PhysicalMemory *physmem;
+// PhysicalMemory *physmem;
FunctionProfile *profile;
ProfileNode *profileNode;
@@ -164,8 +166,6 @@ class CPUExecContext
#else
Process *process;
- FunctionalMemory *mem; // functional storage for process address space
-
// Address space ID. Note that this is used for TIMING cache
// simulation only; all functional memory accesses should use
// one of the FunctionalMemory pointers above.
@@ -202,9 +202,7 @@ class CPUExecContext
CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
#else
- CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
- CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
- int _asid);
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port);
// Constructor to use XC to pass reg file around. Not used for anything
// else.
CPUExecContext(RegFile *regFile);
@@ -238,17 +236,17 @@ class CPUExecContext
int getInstAsid() { return regs.instAsid(); }
int getDataAsid() { return regs.dataAsid(); }
- Fault translateInstReq(MemReqPtr &req)
+ Fault translateInstReq(CpuRequestPtr &req)
{
return itb->translate(req);
}
- Fault translateDataReadReq(MemReqPtr &req)
+ Fault translateDataReadReq(CpuRequestPtr &req)
{
return dtb->translate(req, false);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+ Fault translateDataWriteReq(CpuRequestPtr &req)
{
return dtb->translate(req, true);
}
@@ -265,34 +263,26 @@ class CPUExecContext
int getInstAsid() { return asid; }
int getDataAsid() { return asid; }
- Fault dummyTranslation(MemReqPtr &req)
+ Fault translateInstReq(CpuRequestPtr &req)
{
-#if 0
- assert((req->vaddr >> 48 & 0xffff) == 0);
-#endif
-
- // put the asid in the upper 16 bits of the paddr
- req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
- req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return NoFault;
+ return process->pTable->translate(req);
}
- Fault translateInstReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataReadReq(MemReqPtr &req)
+
+ Fault translateDataReadReq(CpuRequestPtr &req)
{
- return dummyTranslation(req);
+ return process->pTable->translate(req);
}
- Fault translateDataWriteReq(MemReqPtr &req)
+
+ Fault translateDataWriteReq(CpuRequestPtr &req)
{
- return dummyTranslation(req);
+ return process->pTable->translate(req);
}
#endif
+/*
template <class T>
- Fault read(MemReqPtr &req, T &data)
+ Fault read(CpuRequestPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
if (req->flags & LOCKED) {
@@ -302,13 +292,13 @@ class CPUExecContext
#endif
Fault error;
- error = mem->read(req, data);
+ error = mem->prot_read(req->paddr, data, req->size);
data = LittleEndianGuest::gtoh(data);
return error;
}
template <class T>
- Fault write(MemReqPtr &req, T &data)
+ Fault write(CpuRequestPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
ExecContext *xc;
@@ -356,9 +346,9 @@ class CPUExecContext
}
#endif
- return mem->write(req, (T)LittleEndianGuest::htog(data));
+ return mem->prot_write(req->paddr, (T)htog(data), req->size);
}
-
+*/
virtual bool misspeculating();
@@ -369,9 +359,11 @@ class CPUExecContext
inst = new_inst;
}
- Fault instRead(MemReqPtr &req)
+ Fault instRead(CpuRequestPtr &req)
{
- return mem->read(req, inst);
+ panic("instRead not implemented");
+ // return funcPhysMem->read(req, inst);
+ return No_Fault;
}
void setCpuId(int id) { cpu_id = id; }
diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc
index 84b5eacf7..ebb719b2c 100644
--- a/cpu/exetrace.cc
+++ b/cpu/exetrace.cc
@@ -30,9 +30,6 @@
#include <iomanip>
#include "sim/param.hh"
-#include "encumbered/cpu/full/dyn_inst.hh"
-#include "encumbered/cpu/full/spec_state.hh"
-#include "encumbered/cpu/full/issue.hh"
#include "cpu/exetrace.hh"
#include "base/loader/symtab.hh"
#include "cpu/base.hh"
diff --git a/cpu/op_class.cc b/cpu/op_class.cc
new file mode 100644
index 000000000..00136ded5
--- /dev/null
+++ b/cpu/op_class.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2003-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.
+ */
+
+#include "cpu/op_class.hh"
+
+/** OpClass enum -> description string */
+const char *
+opClassStrings[Num_OpClasses] =
+{
+ "(null)",
+ "IntAlu",
+ "IntMult",
+ "IntDiv",
+ "FloatAdd",
+ "FloatCmp",
+ "FloatCvt",
+ "FloatMult",
+ "FloatDiv",
+ "FloatSqrt",
+ "MemRead",
+ "MemWrite",
+ "IprAccess",
+ "InstPrefetch"
+};
+
diff --git a/encumbered/cpu/full/op_class.hh b/cpu/op_class.hh
index ff53b58d2..cdb40a0fb 100644
--- a/encumbered/cpu/full/op_class.hh
+++ b/cpu/op_class.hh
@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
-#define __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
+#ifndef __CPU__OP_CLASS_HH__
+#define __CPU__OP_CLASS_HH__
/**
* @file
@@ -39,26 +39,26 @@
* assigning instructions to functional units.
*/
enum OpClass {
- No_OpClass = 0, /* inst does not use a functional unit */
- IntAluOp, /* integer ALU */
- IntMultOp, /* integer multiplier */
- IntDivOp, /* integer divider */
- FloatAddOp, /* floating point adder/subtractor */
- FloatCmpOp, /* floating point comparator */
- FloatCvtOp, /* floating point<->integer converter */
- FloatMultOp, /* floating point multiplier */
- FloatDivOp, /* floating point divider */
- FloatSqrtOp, /* floating point square root */
- MemReadOp, /* memory read port */
- MemWriteOp, /* memory write port */
- IprAccessOp, /* Internal Processor Register read/write port */
- InstPrefetchOp, /* instruction prefetch port (on I-cache) */
- Num_OpClasses /* total functional unit classes */
+ No_OpClass = 0, ///< Instruction does not use a functional unit
+ IntAluOp, ///< Integer ALU operaton (add/sub/logical)
+ IntMultOp, ///< Integer multiply
+ IntDivOp, ///< Integer divide
+ FloatAddOp, ///< Floating point add/subtract
+ FloatCmpOp, ///< Floating point comparison
+ FloatCvtOp, ///< Floating point<->integer conversion
+ FloatMultOp, ///< Floating point multiply
+ FloatDivOp, ///< Floating point divide
+ FloatSqrtOp, ///< Floating point square root
+ MemReadOp, ///< Memory read port
+ MemWriteOp, ///< Memory write port
+ IprAccessOp, ///< Internal Processor Register read/write port
+ InstPrefetchOp, ///< Instruction prefetch port (on I-cache)
+ Num_OpClasses ///< Total number of operation classes
};
/**
- * Array mapping OpClass enum values to strings. Defined in fu_pool.cc.
+ * Array mapping OpClass enum values to strings. Defined in op_class.cc.
*/
extern const char *opClassStrings[];
-#endif // __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
+#endif // __CPU__OP_CLASS_HH__
diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh
index 7fa3902cc..585aba0f1 100644
--- a/cpu/pc_event.hh
+++ b/cpu/pc_event.hh
@@ -31,17 +31,12 @@
#include <vector>
-#include "mem/mem_req.hh"
-
class ExecContext;
class PCEventQueue;
class PCEvent
{
protected:
- static const Addr badpc = MemReq::inval_addr;
-
- protected:
std::string description;
PCEventQueue *queue;
Addr evpc;
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc
index 8db72b77e..fc70df662 100644
--- a/cpu/simple/cpu.cc
+++ b/cpu/simple/cpu.cc
@@ -53,8 +53,6 @@
#include "cpu/smt.hh"
#include "cpu/static_inst.hh"
#include "kern/kernel_stats.hh"
-#include "mem/base_mem.hh"
-#include "mem/mem_interface.hh"
#include "sim/byteswap.hh"
#include "sim/builder.hh"
#include "sim/debug.hh"
@@ -72,7 +70,7 @@
#include "arch/stacktrace.hh"
#include "arch/vtophys.hh"
#else // !FULL_SYSTEM
-#include "mem/functional/functional.hh"
+#include "mem/memory.hh"
#endif // FULL_SYSTEM
using namespace std;
@@ -116,43 +114,85 @@ SimpleCPU::TickEvent::description()
}
-SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu)
- : Event(&mainEventQueue), cpu(_cpu)
+bool
+SimpleCPU::CpuPort::recvTiming(Packet &pkt)
{
+ cpu->processResponse(pkt);
+ return true;
}
-void SimpleCPU::CacheCompletionEvent::process()
+Tick
+SimpleCPU::CpuPort::recvAtomic(Packet &pkt)
{
- cpu->processCacheCompletion();
+ panic("CPU doesn't expect callback!");
+ return curTick;
}
-const char *
-SimpleCPU::CacheCompletionEvent::description()
+void
+SimpleCPU::CpuPort::recvFunctional(Packet &pkt)
+{
+ panic("CPU doesn't expect callback!");
+}
+
+void
+SimpleCPU::CpuPort::recvStatusChange(Status status)
{
- return "SimpleCPU cache completion event";
+ cpu->recvStatusChange(status);
+}
+
+Packet *
+SimpleCPU::CpuPort::recvRetry()
+{
+ return cpu->processRetry();
}
SimpleCPU::SimpleCPU(Params *p)
- : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL),
- cacheCompletionEvent(this)
+ : BaseCPU(p), icachePort(this),
+ dcachePort(this), tickEvent(this, p->width), cpuXC(NULL)
{
_status = Idle;
+
+ //Create Memory Ports (conect them up)
+ p->mem->addPort("DCACHE");
+ dcachePort.setPeer(p->mem->getPort("DCACHE"));
+ (p->mem->getPort("DCACHE"))->setPeer(&dcachePort);
+
+ p->mem->addPort("ICACHE");
+ icachePort.setPeer(p->mem->getPort("ICACHE"));
+ (p->mem->getPort("ICACHE"))->setPeer(&icachePort);
+
#if FULL_SYSTEM
cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
-
#else
- cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process,
- /* asid */ 0);
+ cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0,
+ &dcachePort);
#endif // !FULL_SYSTEM
- xcProxy = cpuXC->getProxy();
- icacheInterface = p->icache_interface;
- dcacheInterface = p->dcache_interface;
+ xcProxy = cpuXC->getProxy();
- memReq = new MemReq();
- memReq->xc = xcProxy;
- memReq->asid = 0;
- memReq->data = new uint8_t[64];
+#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE
+ ifetch_req = new CpuRequest;
+ ifetch_req->asid = 0;
+ ifetch_req->size = sizeof(MachInst);
+ ifetch_pkt = new Packet;
+ ifetch_pkt->cmd = Read;
+ ifetch_pkt->data = (uint8_t *)&inst;
+ ifetch_pkt->req = ifetch_req;
+ ifetch_pkt->size = sizeof(MachInst);
+
+ data_read_req = new CpuRequest;
+ data_read_req->asid = 0;
+ data_read_pkt = new Packet;
+ data_read_pkt->cmd = Read;
+ data_read_pkt->data = new uint8_t[8];
+ data_read_pkt->req = data_read_req;
+
+ data_write_req = new CpuRequest;
+ data_write_req->asid = 0;
+ data_write_pkt = new Packet;
+ data_write_pkt->cmd = Write;
+ data_write_pkt->req = data_write_req;
+#endif
numInst = 0;
startNumInst = 0;
@@ -172,9 +212,9 @@ void
SimpleCPU::switchOut(Sampler *s)
{
sampler = s;
- if (status() == DcacheMissStall) {
+ if (status() == DcacheWaitResponse) {
DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n");
- _status = DcacheMissSwitch;
+ _status = DcacheWaitSwitch;
}
else {
_status = SwitchedOut;
@@ -287,6 +327,18 @@ SimpleCPU::regStats()
.prereq(dcacheStallCycles)
;
+ icacheRetryCycles
+ .name(name() + ".icache_retry_cycles")
+ .desc("ICache total retry cycles")
+ .prereq(icacheRetryCycles)
+ ;
+
+ dcacheRetryCycles
+ .name(name() + ".dcache_retry_cycles")
+ .desc("DCache total retry cycles")
+ .prereq(dcacheRetryCycles)
+ ;
+
idleFraction = constant(1.0) - notIdleFraction;
}
@@ -308,7 +360,6 @@ SimpleCPU::serialize(ostream &os)
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
nameOut(os, csprintf("%s.cacheCompletionEvent", name()));
- cacheCompletionEvent.serialize(os);
}
void
@@ -319,8 +370,6 @@ SimpleCPU::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(inst);
cpuXC->unserialize(cp, csprintf("%s.xc", section));
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
- cacheCompletionEvent
- .unserialize(cp, csprintf("%s.cacheCompletionEvent", section));
}
void
@@ -331,6 +380,7 @@ change_thread_state(int thread_number, int activate, int priority)
Fault
SimpleCPU::copySrcTranslate(Addr src)
{
+#if 0
static bool no_warn = true;
int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
// Only support block sizes of 64 atm.
@@ -347,8 +397,7 @@ SimpleCPU::copySrcTranslate(Addr src)
memReq->reset(src & ~(blk_size - 1), blk_size);
- // translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
+ // translate to physical address Fault fault = cpuXC->translateDataReadReq(req);
if (fault == NoFault) {
cpuXC->copySrcAddr = src;
@@ -360,11 +409,15 @@ SimpleCPU::copySrcTranslate(Addr src)
cpuXC->copySrcPhysAddr = 0;
}
return fault;
+#else
+ return No_Fault;
+#endif
}
Fault
SimpleCPU::copy(Addr dest)
{
+#if 0
static bool no_warn = true;
int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
// Only support block sizes of 64 atm.
@@ -383,7 +436,7 @@ SimpleCPU::copy(Addr dest)
memReq->reset(dest & ~(blk_size -1), blk_size);
// translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
+ Fault fault = cpuXC->translateDataWriteReq(req);
if (fault == NoFault) {
Addr dest_addr = memReq->paddr + offset;
@@ -407,6 +460,10 @@ SimpleCPU::copy(Addr dest)
assert(!fault->isAlignmentFault());
return fault;
+#else
+ panic("copy not implemented");
+ return No_Fault;
+#endif
}
// precise architected memory state accessor macros
@@ -414,22 +471,64 @@ template <class T>
Fault
SimpleCPU::read(Addr addr, T &data, unsigned flags)
{
- if (status() == DcacheMissStall || status() == DcacheMissSwitch) {
- Fault fault = cpuXC->read(memReq,data);
+ if (status() == DcacheWaitResponse || status() == DcacheWaitSwitch) {
+// Fault fault = xc->read(memReq,data);
+ // Not sure what to check for no fault...
+ if (data_read_pkt->result == Success) {
+ memcpy(&data, data_read_pkt->data, sizeof(T));
+ }
if (traceData) {
traceData->setAddr(addr);
}
- return fault;
+
+ // @todo: Figure out a way to create a Fault from the packet result.
+ return No_Fault;
}
- memReq->reset(addr, sizeof(T), flags);
+// memReq->reset(addr, sizeof(T), flags);
+
+#if SIMPLE_CPU_MEM_TIMING
+ CpuRequest *data_read_req = new CpuRequest;
+#endif
+
+ data_read_req->vaddr = addr;
+ data_read_req->size = sizeof(T);
+ data_read_req->flags = flags;
+ data_read_req->time = curTick;
// translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
+ Fault fault = cpuXC->translateDataReadReq(data_read_req);
+
+ // Now do the access.
+ if (fault == No_Fault) {
+#if SIMPLE_CPU_MEM_TIMING
+ data_read_pkt = new Packet;
+ data_read_pkt->cmd = Read;
+ data_read_pkt->req = data_read_req;
+ data_read_pkt->data = new uint8_t[8];
+#endif
+ data_read_pkt->addr = data_read_req->paddr;
+ data_read_pkt->size = sizeof(T);
- // if we have a cache, do cache access too
- if (fault == NoFault && dcacheInterface) {
+ sendDcacheRequest(data_read_pkt);
+
+#if SIMPLE_CPU_MEM_IMMEDIATE
+ // Need to find a way to not duplicate code above.
+
+ if (data_read_pkt->result == Success) {
+ memcpy(&data, data_read_pkt->data, sizeof(T));
+ }
+
+ if (traceData) {
+ traceData->setAddr(addr);
+ }
+
+ // @todo: Figure out a way to create a Fault from the packet result.
+ return No_Fault;
+#endif
+ }
+/*
memReq->cmd = Read;
memReq->completionEvent = NULL;
memReq->time = curTick;
@@ -454,8 +553,9 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
fault = cpuXC->read(memReq, data);
}
-
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
+*/
+ // This will need a new way to tell if it has a dcache attached.
+ if (data_read_req->flags & UNCACHEABLE)
recordEvent("Uncached Read");
return fault;
@@ -508,11 +608,31 @@ template <class T>
Fault
SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
- memReq->reset(addr, sizeof(T), flags);
+ data_write_req->vaddr = addr;
+ data_write_req->time = curTick;
+ data_write_req->size = sizeof(T);
+ data_write_req->flags = flags;
// translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
+ Fault fault = cpuXC->translateDataWriteReq(data_write_req);
+ // Now do the access.
+ if (fault == No_Fault) {
+#if SIMPLE_CPU_MEM_TIMING
+ data_write_pkt = new Packet;
+ data_write_pkt->cmd = Write;
+ data_write_pkt->req = data_write_req;
+ data_write_pkt->data = new uint8_t[64];
+ memcpy(data_write_pkt->data, &data, sizeof(T));
+#else
+ data_write_pkt->data = (uint8_t *)&data;
+#endif
+ data_write_pkt->addr = data_write_req->paddr;
+ data_write_pkt->size = sizeof(T);
+
+ sendDcacheRequest(data_write_pkt);
+ }
+/*
// do functional access
if (fault == NoFault)
fault = cpuXC->write(memReq, data);
@@ -535,13 +655,16 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
_status = DcacheMissStall;
}
}
-
+*/
if (res && (fault == NoFault))
- *res = memReq->result;
+ *res = data_write_pkt->result;
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
+ // This will need a new way to tell if it's hooked up to a cache or not.
+ if (data_write_req->flags & UNCACHEABLE)
recordEvent("Uncached Write");
+ // If the write needs to have a fault on the access, consider calling
+ // changeStatus() and changing it to "bad addr write" or something.
return fault;
}
@@ -597,36 +720,130 @@ SimpleCPU::dbg_vtophys(Addr addr)
#endif // FULL_SYSTEM
void
-SimpleCPU::processCacheCompletion()
+SimpleCPU::sendIcacheRequest(Packet *pkt)
{
+ assert(!tickEvent.scheduled());
+#if SIMPLE_CPU_MEM_TIMING
+ retry_pkt = pkt;
+ bool success = icachePort.sendTiming(*pkt);
+
+ unscheduleTickEvent();
+
+ lastIcacheStall = curTick;
+
+ if (!success) {
+ // Need to wait for retry
+ _status = IcacheRetry;
+ } else {
+ // Need to wait for cache to respond
+ _status = IcacheWaitResponse;
+ }
+#elif SIMPLE_CPU_MEM_ATOMIC
+ Tick latency = icachePort.sendAtomic(*pkt);
+
+ unscheduleTickEvent();
+ scheduleTickEvent(latency);
+
+ // Note that Icache miss cycles will be incorrect. Unless
+ // we check the status of the packet sent (is this valid?),
+ // we won't know if the latency is a hit or a miss.
+ icacheStallCycles += latency;
+
+ _status = IcacheAccessComplete;
+#elif SIMPLE_CPU_MEM_IMMEDIATE
+ icachePort.sendAtomic(*pkt);
+#else
+#error "SimpleCPU has no mem model set"
+#endif
+}
+
+void
+SimpleCPU::sendDcacheRequest(Packet *pkt)
+{
+ assert(!tickEvent.scheduled());
+#if SIMPLE_CPU_MEM_TIMING
+ unscheduleTickEvent();
+
+ retry_pkt = pkt;
+ bool success = dcachePort.sendTiming(*pkt);
+
+ lastDcacheStall = curTick;
+
+ if (!success) {
+ _status = DcacheRetry;
+ } else {
+ _status = DcacheWaitResponse;
+ }
+#elif SIMPLE_CPU_MEM_ATOMIC
+ unscheduleTickEvent();
+
+ Tick latency = dcachePort.sendAtomic(*pkt);
+
+ scheduleTickEvent(latency);
+
+ // Note that Dcache miss cycles will be incorrect. Unless
+ // we check the status of the packet sent (is this valid?),
+ // we won't know if the latency is a hit or a miss.
+ dcacheStallCycles += latency;
+#elif SIMPLE_CPU_MEM_IMMEDIATE
+ dcachePort.sendAtomic(*pkt);
+#else
+#error "SimpleCPU has no mem model set"
+#endif
+}
+
+void
+SimpleCPU::processResponse(Packet &response)
+{
+ assert(SIMPLE_CPU_MEM_TIMING);
+
+ // For what things is the CPU the consumer of the packet it sent
+ // out? This may create a memory leak if that's the case and it's
+ // expected of the SimpleCPU to delete its own packet.
+ Packet *pkt = &response;
+
switch (status()) {
- case IcacheMissStall:
+ case IcacheWaitResponse:
icacheStallCycles += curTick - lastIcacheStall;
- _status = IcacheMissComplete;
+
+ _status = IcacheAccessComplete;
scheduleTickEvent(1);
+
+ // Copy the icache data into the instruction itself.
+ memcpy(&inst, pkt->data, sizeof(inst));
+
+ delete pkt;
break;
- case DcacheMissStall:
- if (memReq->cmd.isRead()) {
+ case DcacheWaitResponse:
+ if (pkt->cmd == Read) {
curStaticInst->execute(this,traceData);
if (traceData)
traceData->finalize();
}
+
+ delete pkt;
+
dcacheStallCycles += curTick - lastDcacheStall;
_status = Running;
scheduleTickEvent(1);
break;
- case DcacheMissSwitch:
- if (memReq->cmd.isRead()) {
+ case DcacheWaitSwitch:
+ if (pkt->cmd == Read) {
curStaticInst->execute(this,traceData);
if (traceData)
traceData->finalize();
}
+
+ delete pkt;
+
_status = SwitchedOut;
sampler->signalSwitched();
case SwitchedOut:
// If this CPU has been switched out due to sampling/warm-up,
// ignore any further status changes (e.g., due to cache
// misses outstanding at the time of the switch).
+ delete pkt;
+
return;
default:
panic("SimpleCPU::processCacheCompletion: bad state");
@@ -634,6 +851,28 @@ SimpleCPU::processCacheCompletion()
}
}
+Packet *
+SimpleCPU::processRetry()
+{
+#if SIMPLE_CPU_MEM_TIMING
+ switch(status()) {
+ case IcacheRetry:
+ icacheRetryCycles += curTick - lastIcacheStall;
+ return retry_pkt;
+ break;
+ case DcacheRetry:
+ dcacheRetryCycles += curTick - lastDcacheStall;
+ return retry_pkt;
+ break;
+ default:
+ panic("SimpleCPU::processRetry: bad state");
+ break;
+ }
+#else
+ panic("shouldn't be here");
+#endif
+}
+
#if FULL_SYSTEM
void
SimpleCPU::post_interrupt(int int_num, int index)
@@ -706,15 +945,14 @@ SimpleCPU::tick()
cpuXC->setFloatRegDouble(ZeroReg, 0.0);
#endif // TARGET_ALPHA
- if (status() == IcacheMissComplete) {
+ if (status() == IcacheAccessComplete) {
// We've already fetched an instruction and were stalled on an
// I-cache miss. No need to fetch it again.
// Set status to running; tick event will get rescheduled if
// necessary at end of tick() function.
_status = Running;
- }
- else {
+ } else {
// Try to fetch an instruction
// set up memory request for instruction fetch
@@ -724,15 +962,35 @@ SimpleCPU::tick()
#define IFETCH_FLAGS(pc) 0
#endif
- memReq->cmd = Read;
- memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
- IFETCH_FLAGS(cpuXC->readPC()));
+#if SIMPLE_CPU_MEM_TIMING
+ CpuRequest *ifetch_req = new CpuRequest();
+ ifetch_req->size = sizeof(MachInst);
+#endif
- fault = cpuXC->translateInstReq(memReq);
+ ifetch_req->vaddr = cpuXC->readPC() & ~3;
+ ifetch_req->time = curTick;
- if (fault == NoFault)
- fault = cpuXC->mem->read(memReq, inst);
+/* memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t),
+ IFETCH_FLAGS(xc->regs.pc));
+*/
+
+ fault = xc->translateInstReq(ifetch_req);
+
+ if (fault == NoFault) {
+#if SIMPLE_CPU_MEM_TIMING
+ Packet *ifetch_pkt = new Packet;
+ ifetch_pkt->cmd = Read;
+ ifetch_pkt->data = (uint8_t *)&inst;
+ ifetch_pkt->req = ifetch_req;
+ ifetch_pkt->size = sizeof(MachInst);
+#endif
+ ifetch_pkt->addr = ifetch_req->paddr;
+ sendIcacheRequest(ifetch_pkt);
+#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC
+ return;
+#endif
+/*
if (icacheInterface && fault == NoFault) {
memReq->completionEvent = NULL;
@@ -743,7 +1001,7 @@ SimpleCPU::tick()
// Ugly hack to get an event scheduled *only* if the access is
// a miss. We really should add first-class support for this
// at some point.
- if (result != MA_HIT && icacheInterface->doEvents()) {
+ if (result != MA_HIT && icacheInterface->doEvents()) {
memReq->completionEvent = &cacheCompletionEvent;
lastIcacheStall = curTick;
unscheduleTickEvent();
@@ -751,6 +1009,8 @@ SimpleCPU::tick()
return;
}
}
+*/
+ }
}
// If we've got a valid instruction (i.e., no fault on instruction
@@ -806,8 +1066,7 @@ SimpleCPU::tick()
// If we have a dcache miss, then we can't finialize the instruction
// trace yet because we want to populate it with the data later
- if (traceData &&
- !(status() == DcacheMissStall && memReq->cmd.isRead())) {
+ if (traceData && (status() != DcacheWaitResponse)) {
traceData->finalize();
}
@@ -846,7 +1105,7 @@ SimpleCPU::tick()
assert(status() == Running ||
status() == Idle ||
- status() == DcacheMissStall);
+ status() == DcacheWaitResponse);
if (status() == Running && !tickEvent.scheduled())
tickEvent.schedule(curTick + cycles(1));
@@ -866,17 +1125,15 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<FunctionalMemory *> mem;
SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
#else
+ SimObjectParam<Memory *> mem;
SimObjectParam<Process *> workload;
#endif // FULL_SYSTEM
Param<int> clock;
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
Param<bool> defer_registration;
Param<int> width;
@@ -899,17 +1156,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(mem, "memory"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""),
#else
+ INIT_PARAM(mem, "memory"),
INIT_PARAM(workload, "processes to run"),
#endif // FULL_SYSTEM
INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(icache, "L1 instruction cache object"),
- INIT_PARAM(dcache, "L1 data cache object"),
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(width, "cpu width"),
INIT_PARAM(function_trace, "Enable function trace"),
@@ -931,18 +1186,16 @@ CREATE_SIM_OBJECT(SimpleCPU)
params->clock = clock;
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;
- params->icache_interface = (icache) ? icache->getInterface() : NULL;
- params->dcache_interface = (dcache) ? dcache->getInterface() : NULL;
params->width = width;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
- params->mem = mem;
params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
#else
+ params->mem = mem;
params->process = workload;
#endif
diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh
index 4ab9a1c3e..fbfae950f 100644
--- a/cpu/simple/cpu.hh
+++ b/cpu/simple/cpu.hh
@@ -36,6 +36,9 @@
#include "cpu/pc_event.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/static_inst.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "mem/request.hh"
#include "sim/eventq.hh"
// forward declarations
@@ -43,7 +46,7 @@
class Processor;
class AlphaITB;
class AlphaDTB;
-class PhysicalMemory;
+class Memory;
class RemoteGDB;
class GDBListener;
@@ -62,11 +65,48 @@ namespace Trace {
class InstRecord;
}
+
+// Set exactly one of these symbols to 1 to set the memory access
+// model. Probably should make these template parameters, or even
+// just fork the CPU models.
+//
+#define SIMPLE_CPU_MEM_TIMING 0
+#define SIMPLE_CPU_MEM_ATOMIC 0
+#define SIMPLE_CPU_MEM_IMMEDIATE 1
+
+
class SimpleCPU : public BaseCPU
{
protected:
typedef TheISA::MachInst MachInst;
typedef TheISA::MiscReg MiscReg;
+ class CpuPort : public Port
+ {
+
+ SimpleCPU *cpu;
+
+ public:
+
+ CpuPort(SimpleCPU *_cpu)
+ : cpu(_cpu)
+ { }
+
+ protected:
+
+ virtual bool recvTiming(Packet &pkt);
+
+ virtual Tick recvAtomic(Packet &pkt);
+
+ virtual void recvFunctional(Packet &pkt);
+
+ virtual void recvStatusChange(Status status);
+
+ virtual Packet *recvRetry();
+ };
+
+ CpuPort icachePort;
+ CpuPort dcachePort;
+
public:
// main simulation loop (one cycle)
void tick();
@@ -109,10 +149,12 @@ class SimpleCPU : public BaseCPU
enum Status {
Running,
Idle,
- IcacheMissStall,
- IcacheMissComplete,
- DcacheMissStall,
- DcacheMissSwitch,
+ IcacheRetry,
+ IcacheWaitResponse,
+ IcacheAccessComplete,
+ DcacheRetry,
+ DcacheWaitResponse,
+ DcacheWaitSwitch,
SwitchedOut
};
@@ -133,14 +175,12 @@ class SimpleCPU : public BaseCPU
public:
struct Params : public BaseCPU::Params
{
- MemInterface *icache_interface;
- MemInterface *dcache_interface;
int width;
#if FULL_SYSTEM
AlphaITB *itb;
AlphaDTB *dtb;
- FunctionalMemory *mem;
#else
+ Memory *mem;
Process *process;
#endif
};
@@ -162,17 +202,19 @@ class SimpleCPU : public BaseCPU
bool interval_stats;
#endif
- // L1 instruction cache
- MemInterface *icacheInterface;
-
- // L1 data cache
- MemInterface *dcacheInterface;
-
// current instruction
MachInst inst;
- // Refcounted pointer to the one memory request.
- MemReqPtr memReq;
+#if SIMPLE_CPU_MEM_TIMING
+ Packet *retry_pkt;
+#elif SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE
+ CpuRequest *ifetch_req;
+ Packet *ifetch_pkt;
+ CpuRequest *data_read_req;
+ Packet *data_read_pkt;
+ CpuRequest *data_write_req;
+ Packet *data_write_pkt;
+#endif
// Pointer to the sampler that is telling us to switchover.
// Used to signal the completion of the pipe drain and schedule
@@ -181,20 +223,6 @@ class SimpleCPU : public BaseCPU
StaticInstPtr curStaticInst;
- class CacheCompletionEvent : public Event
- {
- private:
- SimpleCPU *cpu;
-
- public:
- CacheCompletionEvent(SimpleCPU *_cpu);
-
- virtual void process();
- virtual const char *description();
- };
-
- CacheCompletionEvent cacheCompletionEvent;
-
Status status() const { return _status; }
virtual void activateContext(int thread_num, int delay);
@@ -227,15 +255,28 @@ class SimpleCPU : public BaseCPU
Stats::Average<> notIdleFraction;
Stats::Formula idleFraction;
- // number of cycles stalled for I-cache misses
+ // number of cycles stalled for I-cache responses
Stats::Scalar<> icacheStallCycles;
Counter lastIcacheStall;
- // number of cycles stalled for D-cache misses
+ // number of cycles stalled for I-cache retries
+ Stats::Scalar<> icacheRetryCycles;
+ Counter lastIcacheRetry;
+
+ // number of cycles stalled for D-cache responses
Stats::Scalar<> dcacheStallCycles;
Counter lastDcacheStall;
- void processCacheCompletion();
+ // number of cycles stalled for D-cache retries
+ Stats::Scalar<> dcacheRetryCycles;
+ Counter lastDcacheRetry;
+
+ void sendIcacheRequest(Packet *pkt);
+ void sendDcacheRequest(Packet *pkt);
+ void processResponse(Packet &response);
+
+ Packet * processRetry();
+ void recvStatusChange(Port::Status status) {}
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 20116554e..2ed2fe61c 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -34,7 +34,7 @@
#include "base/hashmap.hh"
#include "base/refcnt.hh"
-#include "encumbered/cpu/full/op_class.hh"
+#include "cpu/op_class.hh"
#include "sim/host.hh"
#include "arch/isa_traits.hh"
diff --git a/dev/io_device.cc b/dev/io_device.cc
index 6ab876ab8..b580c2805 100644
--- a/dev/io_device.cc
+++ b/dev/io_device.cc
@@ -27,25 +27,119 @@
*/
#include "dev/io_device.hh"
-#include "mem/bus/base_interface.hh"
-#include "mem/bus/dma_interface.hh"
#include "sim/builder.hh"
+void
+PioPort::SendEvent::process()
+{
+ if (port->sendTiming(packet) == Success)
+ return;
+
+ port->transmitList.push_back(&packet);
+}
+
PioDevice::PioDevice(const std::string &name, Platform *p)
- : FunctionalMemory(name), platform(p), pioInterface(NULL), pioLatency(0)
-{}
+ : SimObject(name), platform(p)
+{
+ pioPort = new PioPort(this);
+}
+
+
+bool
+PioDevice::recvTiming(Packet &pkt)
+{
+ device->recvAtomic(pkt);
+ sendTiming(pkt, pkt.responseTime-pkt.requestTime);
+ return Success;
+}
PioDevice::~PioDevice()
{
- if (pioInterface)
+ if (pioPort)
delete pioInterface;
}
-DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice)
+void
+DmaPort::sendDma(Packet &pkt)
+{
+ device->platform->system->memoryMode()
+ {
+ case MemAtomic:
+ }
+}
DmaDevice::DmaDevice(const std::string &name, Platform *p)
- : PioDevice(name, p), dmaInterface(NULL)
-{}
+ : PioDevice(name, p)
+{
+ dmaPort = new dmaPort(this);
+}
+
+void
+DmaPort::dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size,
+ Event *event, uint8_t *data = NULL)
+{
+
+ assert(event);
+
+ int prevSize = 0;
+ Packet basePkt;
+ Request baseReq;
+
+ basePkt.flags = 0;
+ basePkt.coherence = NULL;
+ basePkt.senderState = NULL;
+ basePkt.src = 0;
+ basePkt.dest = 0;
+ basePkt.cmd = cmd;
+ basePkt.result = Unknown;
+ basePkt.request = NULL;
+ baseReq.nicReq = true;
+ baseReq.time = curTick;
+
+ completionEvent = event;
+
+ for (ChunkGenerator gen(addr, size, peerBlockSize());
+ !gen.done(); gen.next()) {
+ Packet *pkt = new Packet(basePkt);
+ Request *req = new Request(baseReq);
+ pkt->addr = gen.addr();
+ pkt->size = gen.size();
+ pkt->req = req;
+ pkt->req->paddr = pkt->addr;
+ pkt->req->size = pkt->size;
+ // Increment the data pointer on a write
+ pkt->data = data ? data + prevSize : NULL ;
+ prevSize = pkt->size;
+
+ sendDma(*pkt);
+ }
+}
+
+
+void
+DmaPort::sendDma(Packet &pkt)
+{
+ // some kind of selction between access methods
+ // more work is going to have to be done to make
+ // switching actually work
+ MemState state = device->platform->system->memState;
+
+ if (state == Timing) {
+ if (sendTiming(pkt) == Failure)
+ transmitList.push_back(&packet);
+ } else if (state == Atomic) {
+ sendAtomic(pkt);
+ completionEvent->schedule(pkt.responseTime - pkt.requestTime);
+ completionEvent == NULL;
+ } else if (state == Functional) {
+ sendFunctional(pkt);
+ // Is this correct???
+ completionEvent->schedule(pkt.responseTime - pkt.requestTime);
+ completionEvent == NULL;
+ } else
+ panic("Unknown memory command state.");
+
+}
DmaDevice::~DmaDevice()
{
@@ -53,5 +147,4 @@ DmaDevice::~DmaDevice()
delete dmaInterface;
}
-DEFINE_SIM_OBJECT_CLASS_NAME("DmaDevice", DmaDevice)
diff --git a/dev/io_device.hh b/dev/io_device.hh
index bcfd062b9..a79c3f20a 100644
--- a/dev/io_device.hh
+++ b/dev/io_device.hh
@@ -29,34 +29,165 @@
#ifndef __DEV_IO_DEVICE_HH__
#define __DEV_IO_DEVICE_HH__
-#include "mem/functional/functional.hh"
+#include "base/chunk_generator.hh"
+#include "mem/port.hh"
+#include "sim/eventq.hh"
-class BaseInterface;
class Bus;
-class HierParams;
class Platform;
-template <class BusType> class DMAInterface;
+class PioDevice;
-class PioDevice : public FunctionalMemory
+class PioPort : public Port
{
protected:
+ PioDevice *device;
+
+ virtual bool recvTiming(Packet &pkt);
+
+ virtual Tick recvAtomic(Packet &pkt)
+ { return device->recvAtomic(pkt) };
+
+ virtual void recvFunctional(Packet &pkt)
+ { device->recvAtomic(pkt) };
+
+ virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner)
+ { device->addressRanges(range_list, owner); }
+
+ void sendTiming(Packet &pkt, Tick time)
+ { new SendEvent(this, pkt, time); }
+
+ class SendEvent : public Event
+ {
+ PioPort *port;
+ Packet packet;
+
+ SendEvent(PioPort *p, Packet &pkt, Tick t)
+ : Event(&mainEventQueue), packet(pkt)
+ { schedule(curTick + t); }
+
+ virtual void process();
+
+ virtual const char *description()
+ { return "Future scheduled sendTiming event"; }
+
+ friend class PioPort;
+ }
+
+ public:
+ PioPort(PioDevice *dev)
+ : device(dev)
+ { }
+
+};
+
+class DmaPort : public Port
+{
+ protected:
+ PioDevice *device;
+ std::list<Packet*> transmitList;
+
+
+ virtual bool recvTiming(Packet &pkt)
+ { completionEvent->schedule(curTick+1); completionEvent = NULL; }
+ virtual Tick recvAtomic(Packet &pkt)
+ { panic("dma port shouldn't be used for pio access."); }
+ virtual void recvFunctional(Packet &pkt)
+ { panic("dma port shouldn't be used for pio access."); }
+
+ virtual void recvStatusChange(Status status)
+ { ; }
+
+ virtual Packet *recvRetry()
+ { return transmitList.pop_front(); }
+
+ virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner)
+ { range_list.clear(); owner = true; }
+
+ void dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size,
+ Event *event, uint8_t *data = NULL);
+
+ void sendDma(Packet &pkt);
+
+ virtual Packet *recvRetry()
+ { return transmitList.pop_front(); }
+
+ class SendEvent : public Event
+ {
+ PioPort *port;
+ Packet packet;
+
+ SendEvent(PioPort *p, Packet &pkt, Tick t)
+ : Event(&mainEventQueue), packet(pkt)
+ { schedule(curTick + t); }
+
+ virtual void process();
+
+ virtual const char *description()
+ { return "Future scheduled sendTiming event"; }
+
+ friend class PioPort;
+ }
+ public:
+ DmaPort(DmaDevice *dev)
+ : device(dev)
+ { }
+
+
+};
+
+
+class PioDevice : public SimObject
+{
+ protected:
+
Platform *platform;
- BaseInterface *pioInterface;
- Tick pioLatency;
+
+ PioPort *pioPort;
+
+ virtual void addressRanges(AddrRangeList &range_list, bool &owner) = 0;
+
+ virtual read(Packet &pkt) = 0;
+
+ virtual write(Packet &pkt) = 0;
+
+ Tick recvAtomic(Packet &pkt)
+ { return pkt->cmd == Read ? this->read(pkt) : this->write(pkt); }
public:
PioDevice(const std::string &name, Platform *p);
+
virtual ~PioDevice();
+
+ virtual Port *getPort(std::string if_name)
+ {
+ if (if_name == "pio")
+ return pioPort;
+ else
+ return NULL;
+ }
};
class DmaDevice : public PioDevice
{
protected:
- DMAInterface<Bus> *dmaInterface;
+ DmaPort *dmaPort;
public:
DmaDevice(const std::string &name, Platform *p);
virtual ~DmaDevice();
+
+ virtual Port *getPort(std::string if_name)
+ {
+ if (if_name == "pio")
+ return pioPort;
+ else if (if_name = "dma")
+ return dmaPort;
+ else
+ return NULL;
+ }
};
+
+
+
#endif // __DEV_IO_DEVICE_HH__
diff --git a/dev/platform.hh b/dev/platform.hh
index 1ee645454..2c37048d4 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -41,6 +41,7 @@ class PciConfigAll;
class IntrControl;
class SimConsole;
class Uart;
+class System;
class Platform : public SimObject
{
@@ -54,6 +55,9 @@ class Platform : public SimObject
/** Pointer to the UART, set by the uart */
Uart *uart;
+ /** Pointer to the system for info about the memory system. */
+ System *system;
+
public:
Platform(const std::string &name, IntrControl *intctrl, PciConfigAll *pci);
virtual ~Platform();
diff --git a/mem/bus.hh b/mem/bus.hh
new file mode 100644
index 000000000..e26065295
--- /dev/null
+++ b/mem/bus.hh
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2002-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.
+ */
+
+/**
+ * @file Decleration of a bus object.
+ */
+
+#ifndef __MEM_BUS_HH__
+#define __MEM_BUS_HH__
+
+#include <string>
+#include <list>
+#include <inttypes.h>
+
+#include "base/range.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "mem/request.hh"
+
+class Bus : public MemObject
+{
+ /** Function called by the port when the bus is recieving a Timing
+ transaction.*/
+ bool recvTiming(Packet &pkt, int id);
+
+ /** Function called by the port when the bus is recieving a Atomic
+ transaction.*/
+ Tick recvAtomic(Packet &pkt, int id);
+
+ /** Function called by the port when the bus is recieving a Functional
+ transaction.*/
+ void recvFunctional(Packet &pkt, int id);
+
+ /** Function called by the port when the bus is recieving a status change.*/
+ void recvStatusChange(Port::Status status, int id);
+
+ /** Decleration of the buses port type, one will be instantiated for each
+ of the interfaces connecting to the bus. */
+ class BusPort : public Port
+ {
+ /** A pointer to the bus to which this port belongs. */
+ Bus *bus;
+
+ /** A id to keep track of the intercafe ID this port is connected to. */
+ int id;
+
+ public:
+
+ /** Constructor for the BusPort.*/
+ BusPort(Bus *_bus, int _id)
+ : bus(_bus), id(_id)
+ { }
+
+ protected:
+
+ /** When reciving a timing request from the peer port (at id),
+ pass it to the bus. */
+ virtual bool recvTiming(Packet &pkt)
+ { return bus->recvTiming(pkt, id); }
+
+ /** When reciving a Atomic requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual Tick recvAtomic(Packet &pkt)
+ { return bus->recvAtomic(pkt, id); }
+
+ /** When reciving a Functional requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual void recvFunctional(Packet &pkt)
+ { bus->recvFunctional(pkt, id); }
+
+ /** When reciving a status changefrom the peer port (at id),
+ pass it to the bus. */
+ virtual void recvStatusChange(Status status)
+ { bus->recvStatusChange(status, id); }
+
+ // This should return all the 'owned' addresses that are
+ // downstream from this bus, yes? That is, the union of all
+ // the 'owned' address ranges of all the other interfaces on
+ // this bus...
+ virtual void addressRanges(AddrRangeList &range_list, bool &owner);
+ };
+
+ /** A count of the number of interfaces connected to this bus. */
+ int num_interfaces;
+
+ /** An array of pointers to the peer port interfaces
+ connected to this bus.*/
+ Port *interfaces[];
+
+ public:
+
+ /** A function used to return the port associated with this bus object. */
+ virtual Port *getPort(const char *if_name)
+ {
+ // if_name ignored? forced to be empty?
+ int id = num_interfaces++;
+ interfaces[id] = new BusPort(this, id);
+ return interfaces[id];
+ }
+};
+
+#endif //__MEM_BUS_HH__
diff --git a/mem/mem_object.hh b/mem/mem_object.hh
new file mode 100644
index 000000000..634fb164a
--- /dev/null
+++ b/mem/mem_object.hh
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2002-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.
+ */
+
+/**
+ * @file
+ * Base Memory Object decleration.
+ */
+
+#ifndef __MEM_MEM_OBJECT_HH__
+#define __MEM_MEM_OBJECT_HH__
+
+#include "sim/sim_object.hh"
+#include "mem/port.hh"
+
+/**
+ * The base MemoryObject class, allows for an accesor function to a
+ * simobj that returns the Port.
+ */
+class MemObject : public SimObject
+{
+ public:
+ MemObject(const std::string &name)
+ : SimObject(name)
+ {};
+
+ public:
+ /** Additional function to return the Port of a memory object. */
+ virtual Port *getPort(const char *if_name) = 0;
+};
+
+#endif //__MEM_MEM_OBJECT_HH__
diff --git a/mem/packet.hh b/mem/packet.hh
new file mode 100644
index 000000000..ef4eb85d9
--- /dev/null
+++ b/mem/packet.hh
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/**
+ * @file
+ * Declaration of the Packet Class, a packet is a transaction occuring
+ * between a single level of the memory heirarchy (ie L1->L2).
+ */
+
+#ifndef __MEM_PACKET_HH__
+#define __MEM_PACKET_HH__
+
+#include "mem/request.hh"
+#include "targetarch/isa_traits.hh"
+#include "sim/root.hh"
+
+struct Packet;
+typedef Packet* PacketPtr;
+typedef uint8_t* PacketDataPtr;
+
+/** List of all commands associated with a packet. */
+enum Command
+{
+ Read,
+ Write
+};
+
+/** The result of a particular pakets request. */
+enum PacketResult
+{
+ Success,
+ BadAddress
+};
+
+class SenderState{};
+class Coherence{};
+
+/**
+ * A Packet is the structure to handle requests between two levels
+ * of the memory system. The Request is a global object that trancends
+ * all of the memory heirarchy, but at each levels interface a packet
+ * is created to transfer data/requests. For example, a request would
+ * be used to initiate a request to go to memory/IOdevices, as the request
+ * passes through the memory system several packets will be created. One
+ * will be created to go between the L1 and L2 caches and another to go to
+ * the next level and so forth.
+ *
+ * Packets are assumed to be returned in the case of a single response. If
+ * the transaction has no response, then the consumer will delete the packet.
+ */
+struct Packet
+{
+ /** The address of the request, could be virtual or physical (depending on
+ cache configurations). */
+ Addr addr;
+
+ /** Flag structure to hold flags for this particular packet */
+ uint64_t flags;
+
+ /** A pointer to the overall request. */
+ RequestPtr req;
+
+ /** A virtual base opaque structure used to hold
+ coherence status messages. */
+ Coherence *coherence; // virtual base opaque,
+ // assert(dynamic_cast<Foo>) etc.
+
+ /** A virtual base opaque structure used to hold the senders state. */
+ SenderState *senderState; // virtual base opaque,
+ // assert(dynamic_cast<Foo>) etc.
+
+ /** A pointer to the data being transfered. It can be differnt sizes
+ at each level of the heirarchy so it belongs in the packet,
+ not request*/
+ PacketDataPtr data;
+
+ /** Indicates the size of the request. */
+ int size;
+
+ /** A index of the source of the transaction. */
+ short src;
+
+ /** A index to the destination of the transaction. */
+ short dest;
+
+ /** The command of the transaction. */
+ Command cmd;
+
+ /** The result of the packet transaction. */
+ PacketResult result;
+
+ /** Accessor function that returns the source index of the packet. */
+ short getSrc() const { return src; }
+
+ /** Accessor function that returns the destination index of
+ the packet. */
+ short getDest() const { return dest; }
+};
+
+#endif //__MEM_PACKET_HH
diff --git a/mem/page_table.cc b/mem/page_table.cc
new file mode 100644
index 000000000..63b60de24
--- /dev/null
+++ b/mem/page_table.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/**
+ * @file
+ * Definitions of page table.
+ */
+#include <string>
+#include <map>
+#include <fstream>
+
+#include "base/bitfield.hh"
+#include "base/intmath.hh"
+#include "base/trace.hh"
+#include "mem/page_table.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+PageTable::PageTable(System *_system, Addr _pageSize)
+ : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))),
+ system(_system)
+{
+ assert(isPowerOf2(pageSize));
+}
+
+PageTable::~PageTable()
+{
+}
+
+Fault
+PageTable::page_check(Addr addr, int size) const
+{
+ if (size < sizeof(uint64_t)) {
+ if (!isPowerOf2(size)) {
+ panic("Invalid request size!\n");
+ return Machine_Check_Fault;
+ }
+
+ if ((size - 1) & addr)
+ return Alignment_Fault;
+ }
+ else {
+ if ((addr & (VMPageSize - 1)) + size > VMPageSize) {
+ panic("Invalid request size!\n");
+ return Machine_Check_Fault;
+ }
+
+ if ((sizeof(uint64_t) - 1) & addr)
+ return Alignment_Fault;
+ }
+
+ return No_Fault;
+}
+
+
+
+
+void
+PageTable::allocate(Addr vaddr, int size)
+{
+ // starting address must be page aligned
+ assert(pageOffset(vaddr) == 0);
+
+ for (; size > 0; size -= pageSize, vaddr += pageSize) {
+ std::map<Addr,Addr>::iterator iter = pTable.find(vaddr);
+
+ if (iter != pTable.end()) {
+ // already mapped
+ fatal("PageTable::allocate: address 0x%x already mapped", vaddr);
+ }
+
+ pTable[vaddr] = system->new_page();
+ }
+}
+
+
+
+bool
+PageTable::translate(Addr vaddr, Addr &paddr)
+{
+ Addr page_addr = pageAlign(vaddr);
+ std::map<Addr,Addr>::iterator iter = pTable.find(page_addr);
+
+ if (iter == pTable.end()) {
+ return false;
+ }
+
+ paddr = iter->second + pageOffset(vaddr);
+ return true;
+}
+
+
+Fault
+PageTable::translate(CpuRequestPtr &req)
+{
+ assert(pageAlign(req->vaddr + req->size - 1) == pageAlign(req->vaddr));
+ if (!translate(req->vaddr, req->paddr)) {
+ return Machine_Check_Fault;
+ }
+ return page_check(req->paddr, req->size);
+}
diff --git a/mem/page_table.hh b/mem/page_table.hh
new file mode 100644
index 000000000..d318783be
--- /dev/null
+++ b/mem/page_table.hh
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/**
+ * @file
+ * Declaration of a non-full system Page Table.
+ */
+
+#ifndef __PAGE_TABLE__
+#define __PAGE_TABLE__
+
+#include <string>
+#include <map>
+
+#include "base/trace.hh"
+#include "mem/request.hh"
+#include "mem/packet.hh"
+#include "sim/sim_object.hh"
+
+class System;
+
+/**
+ * Page Table Decleration.
+ */
+class PageTable
+{
+ protected:
+ std::map<Addr,Addr> pTable;
+
+ const Addr pageSize;
+ const Addr offsetMask;
+
+ System *system;
+
+ public:
+
+ PageTable(System *_system, Addr _pageSize = VMPageSize);
+
+ ~PageTable();
+
+ Addr pageAlign(Addr a) { return (a & ~offsetMask); }
+ Addr pageOffset(Addr a) { return (a & offsetMask); }
+
+ Fault page_check(Addr addr, int size) const;
+
+ void allocate(Addr vaddr, int size);
+
+ /**
+ * Translate function
+ * @param vaddr The virtual address.
+ * @return Physical address from translation.
+ */
+ bool translate(Addr vaddr, Addr &paddr);
+
+ /**
+ * Perform a translation on the memory request, fills in paddr
+ * field of mem_req.
+ * @param req The memory request.
+ */
+ Fault translate(CpuRequestPtr &req);
+
+};
+
+#endif
diff --git a/mem/physical.cc b/mem/physical.cc
new file mode 100644
index 000000000..69544c8fe
--- /dev/null
+++ b/mem/physical.cc
@@ -0,0 +1,378 @@
+/*
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include <cstdio>
+#include <iostream>
+#include <string>
+
+
+#include "base/misc.hh"
+#include "config/full_system.hh"
+#include "mem/physical.hh"
+#include "sim/host.hh"
+#include "sim/builder.hh"
+#include "sim/eventq.hh"
+#include "targetarch/isa_traits.hh"
+
+
+using namespace std;
+
+PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet &pkt, MemoryPort* _m)
+ : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
+{
+
+ this->setFlags(AutoDelete);
+}
+
+void
+PhysicalMemory::MemResponseEvent::process()
+{
+ memoryPort->sendTiming(pkt);
+}
+
+const char *
+PhysicalMemory::MemResponseEvent::description()
+{
+ return "Physical Memory Timing Access respnse event";
+}
+
+PhysicalMemory::PhysicalMemory(const string &n)
+ : Memory(n), base_addr(0), pmem_addr(NULL)
+{
+ // Hardcoded to 128 MB for now.
+ pmem_size = 1 << 27;
+
+ if (pmem_size % TheISA::PageBytes != 0)
+ panic("Memory Size not divisible by page size\n");
+
+ int map_flags = MAP_ANON | MAP_PRIVATE;
+ pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
+ map_flags, -1, 0);
+
+ if (pmem_addr == (void *)MAP_FAILED) {
+ perror("mmap");
+ fatal("Could not mmap!\n");
+ }
+
+ page_ptr = 0;
+}
+
+PhysicalMemory::~PhysicalMemory()
+{
+ if (pmem_addr)
+ munmap(pmem_addr, pmem_size);
+ //Remove memPorts?
+}
+
+Addr
+PhysicalMemory::new_page()
+{
+ Addr return_addr = page_ptr << LogVMPageSize;
+ return_addr += base_addr;
+
+ ++page_ptr;
+ return return_addr;
+}
+
+Port *
+PhysicalMemory::addPort(std::string portName)
+{
+ memoryPortList[portName] = new MemoryPort(this);
+ return memoryPortList[portName];
+}
+
+//
+// little helper for better prot_* error messages
+//
+void
+PhysicalMemory::prot_access_error(Addr addr, int size, Command func)
+{
+ panic("invalid physical memory access!\n"
+ "%s: %i(addr=%#x, size=%d) out of range (max=%#x)\n",
+ name(), func, addr, size, pmem_size - 1);
+}
+
+void
+PhysicalMemory::prot_memset(Addr addr, uint8_t val, int size)
+{
+ if (addr + size >= pmem_size)
+ prot_access_error(addr, size, Write);
+
+ memset(pmem_addr + addr - base_addr, val, size);
+}
+
+int
+PhysicalMemory::deviceBlockSize()
+{
+ //Can accept anysize request
+ return 0;
+}
+
+bool
+PhysicalMemory::doTimingAccess (Packet &pkt, MemoryPort* memoryPort)
+{
+ doFunctionalAccess(pkt);
+
+ MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
+ response->schedule(curTick + lat);
+
+ return true;
+}
+
+Tick
+PhysicalMemory::doAtomicAccess(Packet &pkt)
+{
+ doFunctionalAccess(pkt);
+ return curTick + lat;
+}
+
+void
+PhysicalMemory::doFunctionalAccess(Packet &pkt)
+{
+ if (pkt.addr + pkt.size >= pmem_size)
+ prot_access_error(pkt.addr, pkt.size, pkt.cmd);
+
+ switch (pkt.cmd) {
+ case Read:
+ memcpy(pkt.data, pmem_addr + pkt.addr - base_addr, pkt.size);
+ break;
+ case Write:
+ memcpy(pmem_addr + pkt.addr - base_addr, pkt.data, pkt.size);
+ break;
+ default:
+ panic("unimplemented");
+ }
+
+ pkt.result = Success;
+}
+
+Port *
+PhysicalMemory::getPort(const char *if_name)
+{
+ if (memoryPortList.find(if_name) != memoryPortList.end())
+ return memoryPortList[if_name];
+ else
+ panic("Looking for a port that didn't exist\n");
+}
+
+void
+PhysicalMemory::recvStatusChange(Port::Status status)
+{
+ panic("??");
+}
+
+PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory)
+ : memory(_memory)
+{ }
+
+void
+PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
+{
+ memory->recvStatusChange(status);
+}
+
+void
+PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &range_list,
+ bool &owner)
+{
+ panic("??");
+}
+
+int
+PhysicalMemory::MemoryPort::deviceBlockSize()
+{
+ return memory->deviceBlockSize();
+}
+
+bool
+PhysicalMemory::MemoryPort::recvTiming(Packet &pkt)
+{
+ return memory->doTimingAccess(pkt, this);
+}
+
+Tick
+PhysicalMemory::MemoryPort::recvAtomic(Packet &pkt)
+{
+ return memory->doAtomicAccess(pkt);
+}
+
+void
+PhysicalMemory::MemoryPort::recvFunctional(Packet &pkt)
+{
+ memory->doFunctionalAccess(pkt);
+}
+
+
+
+void
+PhysicalMemory::serialize(ostream &os)
+{
+ gzFile compressedMem;
+ string filename = name() + ".physmem";
+
+ SERIALIZE_SCALAR(pmem_size);
+ SERIALIZE_SCALAR(filename);
+
+ // 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, pmem_addr, pmem_size) != pmem_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);
+}
+
+void
+PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
+{
+ gzFile compressedMem;
+ long *tempPage;
+ long *pmem_current;
+ uint64_t curSize;
+ uint32_t bytesRead;
+ const int chunkSize = 16384;
+
+
+ // unmap file that was mmaped in the constructor
+ munmap(pmem_addr, pmem_size);
+
+ string filename;
+
+ UNSERIALIZE_SCALAR(pmem_size);
+ 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);
+
+
+ pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+
+ if (pmem_addr == (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 < pmem_size) {
+ bytesRead = gzread(compressedMem, tempPage, chunkSize);
+ if (bytesRead != chunkSize && bytesRead != pmem_size - curSize)
+ fatal("Read failed on physical memory checkpoint file '%s'"
+ " got %d bytes, expected %d or %d bytes\n",
+ filename, bytesRead, chunkSize, pmem_size-curSize);
+
+ assert(bytesRead % sizeof(long) == 0);
+
+ for (int x = 0; x < bytesRead/sizeof(long); x++)
+ {
+ if (*(tempPage+x) != 0) {
+ pmem_current = (long*)(pmem_addr + 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);
+
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+ Param<string> file;
+#if FULL_SYSTEM
+ SimObjectParam<MemoryController *> mmu;
+#endif
+ Param<Range<Addr> > range;
+
+END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+ INIT_PARAM_DFLT(file, "memory mapped file", ""),
+#if FULL_SYSTEM
+ INIT_PARAM(mmu, "Memory Controller"),
+#endif
+ INIT_PARAM(range, "Device Address Range")
+
+END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
+
+CREATE_SIM_OBJECT(PhysicalMemory)
+{
+#if FULL_SYSTEM
+ if (mmu) {
+ return new PhysicalMemory(getInstanceName(), range, mmu, file);
+ }
+#endif
+
+ return new PhysicalMemory(getInstanceName());
+}
+
+REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
diff --git a/mem/physical.hh b/mem/physical.hh
new file mode 100644
index 000000000..854886a27
--- /dev/null
+++ b/mem/physical.hh
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+/* @file
+ */
+
+#ifndef __PHYSICAL_MEMORY_HH__
+#define __PHYSICAL_MEMORY_HH__
+
+#include "base/range.hh"
+#include "mem/memory.hh"
+#include "mem/packet.hh"
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+#include <map>
+#include <string>
+//
+// Functional model for a contiguous block of physical memory. (i.e. RAM)
+//
+class PhysicalMemory : public Memory
+{
+ class MemoryPort : public Port
+ {
+ PhysicalMemory *memory;
+
+ public:
+
+ MemoryPort(PhysicalMemory *_memory);
+
+ protected:
+
+ virtual bool recvTiming(Packet &pkt);
+
+ virtual Tick recvAtomic(Packet &pkt);
+
+ virtual void recvFunctional(Packet &pkt);
+
+ virtual void recvStatusChange(Status status);
+
+ virtual void getDeviceAddressRanges(AddrRangeList &range_list,
+ bool &owner);
+
+ virtual int deviceBlockSize();
+ };
+
+ std::map<std::string, MemoryPort*> memoryPortList;
+
+ virtual Port * getPort(const char *if_name);
+
+ virtual Port * addPort(std::string portName);
+
+ int numPorts;
+
+ int lat;
+
+ struct MemResponseEvent : public Event
+ {
+ Packet &pkt;
+ MemoryPort *memoryPort;
+
+ MemResponseEvent(Packet &pkt, MemoryPort *memoryPort);
+ void process();
+ const char *description();
+ };
+
+ private:
+ // prevent copying of a MainMemory object
+ PhysicalMemory(const PhysicalMemory &specmem);
+ const PhysicalMemory &operator=(const PhysicalMemory &specmem);
+
+ protected:
+ Addr base_addr;
+ Addr pmem_size;
+ uint8_t *pmem_addr;
+ int page_ptr;
+
+ public:
+ Addr new_page();
+ uint64_t size() { return pmem_size; }
+
+ public:
+ PhysicalMemory(const std::string &n);
+ virtual ~PhysicalMemory();
+
+ protected:
+ // error handling for prot_* functions
+ void prot_access_error(Addr addr, int size, Command func);
+
+ public:
+ int deviceBlockSize();
+
+ void prot_memset(Addr addr, uint8_t val, int size);
+
+ // fast back-door memory access for vtophys(), remote gdb, etc.
+ // uint64_t phys_read_qword(Addr addr) const;
+ private:
+ bool doTimingAccess(Packet &pkt, MemoryPort *memoryPort);
+ Tick doAtomicAccess(Packet &pkt);
+ void doFunctionalAccess(Packet &pkt);
+
+ void recvStatusChange(Port::Status status);
+
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+/*uint64_t
+PhysicalMemory::phys_read_qword(Addr addr) const
+{
+ if (addr + sizeof(uint64_t) > pmem_size)
+ return 0;
+
+ return *(uint64_t *)(pmem_addr + addr);
+}*/
+
+
+#endif //__PHYSICAL_MEMORY_HH__
diff --git a/mem/port.cc b/mem/port.cc
new file mode 100644
index 000000000..75362b472
--- /dev/null
+++ b/mem/port.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2002-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.
+ */
+
+/**
+ * @file Port object definitions.
+ */
+
+#include "base/chunk_generator.hh"
+#include "mem/port.hh"
+
+void
+Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
+{
+ Request req;
+ Packet pkt;
+ pkt.req = &req;
+ pkt.cmd = cmd;
+
+ for (ChunkGenerator gen(addr, size, peerBlockSize());
+ !gen.done(); gen.next()) {
+ pkt.addr = req.paddr = gen.addr();
+ pkt.size = req.size = gen.size();
+ pkt.data = p;
+ sendFunctional(pkt);
+ p += gen.size();
+ }
+}
+
+void
+Port::writeBlobFunctional(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Write);
+}
+
+void
+Port::readBlobFunctional(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Read);
+}
+
+void
+Port::memsetBlobFunctional(Addr addr, uint8_t val, int size)
+{
+ // quick and dirty...
+ uint8_t *buf = new uint8_t[size];
+
+ memset(buf, val, size);
+ blobHelper(addr, buf, size, Write);
+
+ delete buf;
+}
diff --git a/mem/port.hh b/mem/port.hh
new file mode 100644
index 000000000..9d0bd7968
--- /dev/null
+++ b/mem/port.hh
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2002-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.
+ */
+
+/**
+ * @file
+ * Port Object Decleration. Ports are used to interface memory objects to
+ * each other. They will always come in pairs, and we refer to the other
+ * port object as the peer. These are used to make the design more
+ * modular so that a specific interface between every type of objcet doesn't
+ * have to be created.
+ */
+
+#ifndef __MEM_PORT_HH__
+#define __MEM_PORT_HH__
+
+#include <string>
+#include <list>
+#include <inttypes.h>
+
+#include "base/range.hh"
+#include "mem/packet.hh"
+#include "mem/request.hh"
+
+/** This typedef is used to clean up the parameter list of
+ * getDeviceAddressRanges() and getPeerAddressRanges(). It's declared
+ * outside the Port object since it's also used by some mem objects.
+ * Eventually we should move this typedef to wherever Addr is
+ * defined.
+ */
+
+typedef std::list<Range<Addr> > AddrRangeList;
+
+/**
+ * Ports are used to interface memory objects to
+ * each other. They will always come in pairs, and we refer to the other
+ * port object as the peer. These are used to make the design more
+ * modular so that a specific interface between every type of objcet doesn't
+ * have to be created.
+ *
+ * Recv accesor functions are being called from the peer interface.
+ * Send accessor functions are being called from the device the port is
+ * associated with, and it will call the peer recv. accessor function.
+ */
+class Port
+{
+ public:
+
+ // mey be better to use subclasses & RTTI?
+ /** Holds the ports status. Keeps track if it is blocked, or has
+ calculated a range change. */
+ enum Status {
+ Blocked,
+ Unblocked,
+ RangeChange
+ };
+
+ private:
+
+ /** A pointer to the peer port. Ports always come in pairs, that way they
+ can use a standardized interface to communicate between different
+ memory objects. */
+ Port *peer;
+
+ public:
+
+ /** Function to set the pointer for the peer port.
+ @todo should be called by the configuration stuff (python).
+ */
+ void setPeer(Port *port) { peer = port; }
+
+ /** Function to set the pointer for the peer port.
+ @todo should be called by the configuration stuff (python).
+ */
+ Port *getPeer() { return peer; }
+
+ protected:
+
+ /** These functions are protected because they should only be
+ * called by a peer port, never directly by any outside object. */
+
+ /** Called to recive a timing call from the peer port. */
+ virtual bool recvTiming(Packet &pkt) = 0;
+
+ /** Called to recive a atomic call from the peer port. */
+ virtual Tick recvAtomic(Packet &pkt) = 0;
+
+ /** Called to recive a functional call from the peer port. */
+ virtual void recvFunctional(Packet &pkt) = 0;
+
+ /** Called to recieve a status change from the peer port. */
+ virtual void recvStatusChange(Status status) = 0;
+
+ /** Called by a peer port if the send was unsuccesful, and had to
+ wait. This shouldn't be valid for response paths (IO Devices).
+ so it is set to panic if it isn't already defined.
+ */
+ virtual Packet *recvRetry() { panic("??"); }
+
+ /** Called by a peer port in order to determine the block size of the
+ device connected to this port. It sometimes doesn't make sense for
+ this function to be called, a DMA interface doesn't really have a
+ block size, so it is defaulted to a panic.
+ */
+ virtual int deviceBlockSize() { panic("??"); }
+
+ /** The peer port is requesting us to reply with a list of the ranges we
+ are responsible for.
+ @param owner is an output param that, if set, indicates that the
+ port is the owner of the specified ranges (i.e., slave, default
+ responder, etc.). If 'owner' is false, the interface is
+ interested in the specified ranges for snooping purposes. If
+ an object wants to own some ranges and snoop on others, it will
+ need to use two different ports.
+ */
+ virtual void getDeviceAddressRanges(AddrRangeList &range_list,
+ bool &owner)
+ { panic("??"); }
+
+ public:
+
+ /** Function called by associated memory device (cache, memory, iodevice)
+ in order to send a timing request to the port. Simply calls the peer
+ port receive function.
+ @return This function returns if the send was succesful in it's
+ recieve. If it was a failure, then the port will wait for a recvRetry
+ at which point it can issue a successful sendTiming. This is used in
+ case a cache has a higher priority request come in while waiting for
+ the bus to arbitrate.
+ */
+ bool sendTiming(Packet &pkt) { return peer->recvTiming(pkt); }
+
+ /** Function called by the associated device to send an atomic access,
+ an access in which the data is moved and the state is updated in one
+ cycle, without interleaving with other memory accesses.
+ */
+ Tick sendAtomic(Packet &pkt)
+ { return peer->recvAtomic(pkt); }
+
+ /** Function called by the associated device to send a functional access,
+ an access in which the data is instantly updated everywhere in the
+ memory system, without affecting the current state of any block
+ or moving the block.
+ */
+ void sendFunctional(Packet &pkt)
+ { return peer->recvFunctional(pkt); }
+
+ /** Called by the associated device to send a status change to the device
+ connected to the peer interface.
+ */
+ void sendStatusChange(Status status) {peer->recvStatusChange(status); }
+
+ /** When a timing access doesn't return a success, some time later the
+ Retry will be sent.
+ */
+ Packet *sendRetry() { return peer->recvRetry(); }
+
+ /** Called by the associated device if it wishes to find out the blocksize
+ of the device on attached to the peer port.
+ */
+ int peerBlockSize() { return peer->deviceBlockSize(); }
+
+ /** Called by the associated device if it wishes to find out the address
+ ranges connected to the peer ports devices.
+ */
+ void getPeerAddressRanges(AddrRangeList &range_list, bool &owner)
+ { peer->getDeviceAddressRanges(range_list, owner); }
+
+ // Do we need similar wrappers for sendAtomic()? If not, should
+ // we drop the "Functional" from the names?
+
+ /** This function is a wrapper around sendFunctional()
+ that breaks a larger, arbitrarily aligned access into
+ appropriate chunks. The default implementation can use
+ getBlockSize() to determine the block size and go from there.
+ */
+ void readBlobFunctional(Addr addr, uint8_t *p, int size);
+
+ /** This function is a wrapper around sendFunctional()
+ that breaks a larger, arbitrarily aligned access into
+ appropriate chunks. The default implementation can use
+ getBlockSize() to determine the block size and go from there.
+ */
+ void writeBlobFunctional(Addr addr, uint8_t *p, int size);
+
+ /** Fill size bytes starting at addr with byte value val. This
+ should not need to be virtual, since it can be implemented in
+ terms of writeBlobFunctional(). However, it shouldn't be
+ performance-critical either, so it could be if we wanted to.
+ Not even sure if this is actually needed anywhere (there's a
+ prot_memset on the old functional memory that's never used),
+ but Nate claims it is.
+ */
+ void memsetBlobFunctional(Addr addr, uint8_t val, int size);
+
+ private:
+
+ /** Internal helper function for read/writeBlob().
+ */
+ void blobHelper(Addr addr, uint8_t *p, int size, Command cmd);
+};
+
+#endif //__MEM_PORT_HH__
diff --git a/mem/request.hh b/mem/request.hh
new file mode 100644
index 000000000..c3c1d0fd4
--- /dev/null
+++ b/mem/request.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2002-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.
+ */
+
+/**
+ * @file Decleration of a request, the overall memory request consisting of
+ the parts of the request that are persistent throughout the transaction.
+ */
+
+#ifndef __MEM_REQUEST_HH__
+#define __MEM_REQUEST_HH__
+
+#include "targetarch/isa_traits.hh"
+
+class Request;
+class CpuRequest;
+
+typedef Request* RequestPtr;
+typedef CpuRequest* CpuRequestPtr;
+
+/** The request is a Load locked/store conditional. */
+const unsigned LOCKED = 0x001;
+/** The virtual address is also the physical address. */
+const unsigned PHYSICAL = 0x002;
+/** The request is an ALPHA VPTE pal access (hw_ld). */
+const unsigned VPTE = 0x004;
+/** Use the alternate mode bits in ALPHA. */
+const unsigned ALTMODE = 0x008;
+/** The request is to an uncacheable address. */
+const unsigned UNCACHEABLE = 0x010;
+/** The request should not cause a page fault. */
+const unsigned NO_FAULT = 0x020;
+/** The request should be prefetched into the exclusive state. */
+const unsigned PF_EXCLUSIVE = 0x100;
+/** The request should be marked as LRU. */
+const unsigned EVICT_NEXT = 0x200;
+
+class Request
+{
+ //@todo Make Accesor functions, make these private.
+ public:
+ /** The physical address of the request. */
+ Addr paddr;
+
+ /** whether this req came from the CPU or not **DO we need this??***/
+ bool nicReq;
+
+ /** The size of the request. */
+ int size;
+
+ /** The time this request was started. Used to calculate latencies. */
+ Tick time;
+
+ /** Destination address if this is a block copy. */
+ Addr copyDest;
+
+ uint32_t flags;
+};
+
+class CpuRequest : public Request
+{
+ //@todo Make Accesor functions, make these private.
+ public:
+ /** The virtual address of the request. */
+ Addr vaddr;
+
+ /** The address space ID. */
+ int asid;
+
+ /** The return value of store conditional. */
+ uint64_t scResult;
+
+ /** The cpu number for statistics. */
+ int cpuNum;
+
+ /** The requesting thread id. */
+ int threadNum;
+
+ /** program counter of initiating access; for tracing/debugging */
+ Addr pc;
+};
+
+#endif // __MEM_REQUEST_HH__
diff --git a/mem/translating_port.cc b/mem/translating_port.cc
new file mode 100644
index 000000000..f4f2ca737
--- /dev/null
+++ b/mem/translating_port.cc
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#include <string>
+#include "base/chunk_generator.hh"
+#include "mem/port.hh"
+#include "mem/translating_port.hh"
+#include "mem/page_table.hh"
+
+TranslatingPort::TranslatingPort(Port *_port, PageTable *p_table)
+ : port(_port), pTable(p_table)
+{ }
+
+TranslatingPort::~TranslatingPort()
+{ }
+
+Fault
+TranslatingPort::readBlobFunctional(Addr addr, uint8_t *p, int size)
+{
+ Addr paddr;
+ int prevSize = 0;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(),paddr))
+ return Machine_Check_Fault;
+
+ port->readBlobFunctional(paddr, p + prevSize, gen.size());
+ prevSize += gen.size();
+ }
+
+ return No_Fault;
+}
+
+Fault
+TranslatingPort::writeBlobFunctional(Addr addr, uint8_t *p, int size,
+ bool alloc)
+{
+ Addr paddr;
+ int prevSize = 0;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(), paddr)) {
+ if (alloc) {
+ pTable->allocate(roundDown(gen.addr(), VMPageSize),
+ VMPageSize);
+ pTable->translate(gen.addr(), paddr);
+ } else {
+ return Machine_Check_Fault;
+ }
+ }
+
+ port->writeBlobFunctional(paddr, p + prevSize, gen.size());
+ prevSize += gen.size();
+ }
+
+ return No_Fault;
+}
+
+
+Fault
+TranslatingPort::memsetBlobFunctional(Addr addr, uint8_t val, int size,
+ bool alloc)
+{
+ Addr paddr;
+
+ for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
+
+ if (!pTable->translate(gen.addr(), paddr)) {
+ if (alloc) {
+ pTable->allocate(roundDown(gen.addr(), VMPageSize),
+ VMPageSize);
+ pTable->translate(gen.addr(), paddr);
+ } else {
+ return Machine_Check_Fault;
+ }
+ }
+
+ port->memsetBlobFunctional(paddr, val, gen.size());
+ }
+
+ return No_Fault;
+}
+
+
+Fault
+TranslatingPort::writeStringFunctional(Addr addr, const char *str)
+{
+ Addr paddr,vaddr;
+ uint8_t c;
+
+ vaddr = addr;
+
+ do {
+ c = *str++;
+ if (!pTable->translate(vaddr++,paddr))
+ return Machine_Check_Fault;
+
+ port->writeBlobFunctional(paddr, &c, 1);
+ } while (c);
+
+ return No_Fault;
+}
+
+Fault
+TranslatingPort::readStringFunctional(std::string &str, Addr addr)
+{
+ Addr paddr,vaddr;
+ uint8_t c;
+
+ vaddr = addr;
+
+ do {
+ if (!pTable->translate(vaddr++,paddr))
+ return Machine_Check_Fault;
+
+ port->readBlobFunctional(paddr, &c, 1);
+ str += c;
+ } while (c);
+
+ return No_Fault;
+}
+
diff --git a/mem/translating_port.hh b/mem/translating_port.hh
new file mode 100644
index 000000000..1a334c103
--- /dev/null
+++ b/mem/translating_port.hh
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#ifndef __MEM_TRANSLATING_PROT_HH__
+#define __MEM_TRANSLATING_PROT_HH__
+
+#include "mem/memory.hh"
+
+class Port;
+class PageTable;
+
+class TranslatingPort
+{
+ private:
+ Port *port;
+ PageTable *pTable;
+
+ TranslatingPort(const TranslatingPort &specmem);
+ const TranslatingPort &operator=(const TranslatingPort &specmem);
+
+ public:
+ TranslatingPort(Port *_port, PageTable *p_table);
+ virtual ~TranslatingPort();
+
+ public:
+ Fault readBlobFunctional(Addr addr, uint8_t *p, int size);
+ Fault writeBlobFunctional(Addr addr, uint8_t *p, int size,
+ bool alloc = false);
+ Fault memsetBlobFunctional(Addr addr, uint8_t val, int size,
+ bool alloc = false);
+ Fault writeStringFunctional(Addr addr, const char *str);
+ Fault readStringFunctional(std::string &str, Addr addr);
+
+};
+
+#endif
diff --git a/python/m5/objects/BaseCPU.py b/python/m5/objects/BaseCPU.py
index a90203729..07cb850f1 100644
--- a/python/m5/objects/BaseCPU.py
+++ b/python/m5/objects/BaseCPU.py
@@ -2,16 +2,14 @@ from m5 import *
class BaseCPU(SimObject):
type = 'BaseCPU'
abstract = True
- icache = Param.BaseMem(NULL, "L1 instruction cache object")
- dcache = Param.BaseMem(NULL, "L1 data cache object")
if build_env['FULL_SYSTEM']:
dtb = Param.AlphaDTB("Data TLB")
itb = Param.AlphaITB("Instruction TLB")
- mem = Param.FunctionalMemory("memory")
system = Param.System(Parent.any, "system object")
cpu_id = Param.Int(-1, "CPU identifier")
else:
+ mem = Param.Memory(Parent.any, "memory")
workload = VectorParam.Process("processes to run")
max_insts_all_threads = Param.Counter(0,
diff --git a/python/m5/objects/Ethernet.py b/python/m5/objects/Ethernet.py
index 6113e656f..22714e15c 100644
--- a/python/m5/objects/Ethernet.py
+++ b/python/m5/objects/Ethernet.py
@@ -69,7 +69,6 @@ class EtherDevBase(PciDevice):
physmem = Param.PhysicalMemory(Parent.any, "Physical Memory")
- hier = Param.HierParams(Parent.any, "Hierarchy global variables")
payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
dma_read_delay = Param.Latency('0us', "fixed delay for dma reads")
dma_read_factor = Param.Latency('0us', "multiplier for dma reads")
diff --git a/python/m5/objects/MemObject.py b/python/m5/objects/MemObject.py
new file mode 100644
index 000000000..4d68243e6
--- /dev/null
+++ b/python/m5/objects/MemObject.py
@@ -0,0 +1,5 @@
+from m5 import *
+
+class MemObject(SimObject):
+ type = 'MemObject'
+ abstract = True
diff --git a/python/m5/objects/PhysicalMemory.py b/python/m5/objects/PhysicalMemory.py
index f50937ee6..b0aba1a7d 100644
--- a/python/m5/objects/PhysicalMemory.py
+++ b/python/m5/objects/PhysicalMemory.py
@@ -1,8 +1,9 @@
from m5 import *
-from FunctionalMemory import FunctionalMemory
+from Memory import Memory
-class PhysicalMemory(FunctionalMemory):
+class PhysicalMemory(Memory):
type = 'PhysicalMemory'
range = Param.AddrRange("Device Address")
file = Param.String('', "memory mapped file")
- mmu = Param.MemoryController(Parent.any, "Memory Controller")
+ if build_env['FULL_SYSTEM']:
+ mmu = Param.MemoryController(Parent.any, "Memory Controller")
diff --git a/python/m5/objects/Process.py b/python/m5/objects/Process.py
index b4ccc1bec..def70dbaa 100644
--- a/python/m5/objects/Process.py
+++ b/python/m5/objects/Process.py
@@ -3,6 +3,7 @@ class Process(SimObject):
type = 'Process'
abstract = True
output = Param.String('cout', 'filename for stdout/stderr')
+ system = Param.System(Parent.any, "system process will run on")
class LiveProcess(Process):
type = 'LiveProcess'
diff --git a/python/m5/objects/Root.py b/python/m5/objects/Root.py
index 23b13fc67..f51516098 100644
--- a/python/m5/objects/Root.py
+++ b/python/m5/objects/Root.py
@@ -1,5 +1,4 @@
from m5 import *
-from HierParams import HierParams
from Serialize import Serialize
from Statistics import Statistics
from Trace import Trace
@@ -13,12 +12,9 @@ class Root(SimObject):
"print a progress message every n ticks (0 = never)")
output_file = Param.String('cout', "file to dump simulator output to")
checkpoint = Param.String('', "checkpoint file to load")
-# hier = Param.HierParams(HierParams(do_data = False, do_events = True),
-# "shared memory hierarchy parameters")
# stats = Param.Statistics(Statistics(), "statistics object")
# trace = Param.Trace(Trace(), "trace object")
# serialize = Param.Serialize(Serialize(), "checkpoint generation options")
- hier = HierParams(do_data = False, do_events = True)
stats = Statistics()
trace = Trace()
exetrace = ExecutionTrace()
diff --git a/sim/process.cc b/sim/process.cc
index f02ca8bfd..70a92a604 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -42,12 +42,15 @@
#include "cpu/smt.hh"
#include "encumbered/cpu/full/thread.hh"
#include "encumbered/eio/eio.hh"
-#include "encumbered/mem/functional/main.hh"
+#include "mem/page_table.hh"
+#include "mem/memory.hh"
+#include "mem/translating_port.hh"
#include "sim/builder.hh"
#include "sim/fake_syscall.hh"
#include "sim/process.hh"
#include "sim/stats.hh"
#include "sim/syscall_emul.hh"
+#include "sim/system.hh"
#include "arch/process.hh"
@@ -67,20 +70,12 @@ using namespace TheISA;
int num_processes = 0;
Process::Process(const string &nm,
+ System *_system,
int stdin_fd, // initial I/O descriptors
int stdout_fd,
int stderr_fd)
- : SimObject(nm)
+ : SimObject(nm), system(_system)
{
- // allocate memory space
- memory = new MainMemory(nm + ".MainMem");
-
- // allocate initial register file
- init_regs = new RegFile;
- memset(init_regs, 0, sizeof(RegFile));
-
- cpuXC = new CPUExecContext(init_regs);
-
// initialize first 3 fds (stdin, stdout, stderr)
fd_map[STDIN_FILENO] = stdin_fd;
fd_map[STDOUT_FILENO] = stdout_fd;
@@ -93,9 +88,11 @@ Process::Process(const string &nm,
mmap_start = mmap_end = 0;
nxm_start = nxm_end = 0;
+ pTable = new PageTable(system);
// other parameters will be initialized when the program is loaded
}
+
void
Process::regStats()
{
@@ -147,12 +144,7 @@ Process::registerExecContext(ExecContext *xc)
int myIndex = execContexts.size();
execContexts.push_back(xc);
- if (myIndex == 0) {
- // copy process's initial regs struct
- xc->copyArchRegs(cpuXC->getProxy());
- }
-
- // return CPU number to caller and increment available CPU count
+ // return CPU number to caller
return myIndex;
}
@@ -160,7 +152,9 @@ void
Process::startup()
{
if (execContexts.empty())
- return;
+ fatal("Process %s is not associated with any CPUs!\n", name());
+
+ initVirtMem = new TranslatingPort((system->physmem->getPort("DCACHE"))->getPeer(), pTable);
// first exec context for this process... initialize & enable
ExecContext *xc = execContexts[0];
@@ -251,25 +245,28 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process)
static void
copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
- FunctionalMemory *memory)
+ TranslatingPort* memPort)
{
Addr data_ptr_swap;
for (int i = 0; i < strings.size(); ++i) {
data_ptr_swap = htog(data_ptr);
- memory->access(Write, array_ptr, &data_ptr_swap, sizeof(Addr));
- memory->writeString(data_ptr, strings[i].c_str());
+ memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr));
+ memPort->writeStringFunctional(data_ptr, strings[i].c_str());
array_ptr += sizeof(Addr);
data_ptr += strings[i].size() + 1;
}
// add NULL terminator
data_ptr = 0;
- memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
+
+ memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr));
}
-LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
+LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile,
+ System *_system,
int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp)
- : Process(nm, stdin_fd, stdout_fd, stderr_fd)
+ vector<string> &_argv, vector<string> &_envp)
+ : Process(nm, _system, stdin_fd, stdout_fd, stderr_fd),
+ objFile(_objFile), argv(_argv), envp(_envp)
{
prog_fname = argv[0];
@@ -280,8 +277,16 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
data_size = objFile->dataSize() + objFile->bssSize();
brk_point = roundUp(data_base + data_size, VMPageSize);
- // load object file into target memory
- objFile->loadSections(memory);
+ // Set up stack. On Alpha, stack goes below text section. This
+ // code should get moved to some architecture-specific spot.
+ stack_base = text_base - (409600+4096);
+
+ // Set up region for mmaps. Tru64 seems to start just above 0 and
+ // grow up from there.
+ mmap_start = mmap_end = 0x10000;
+
+ // Set pointer for next thread stack. Reserve 8M for main stack.
+ next_thread_stack_base = stack_base - (8 * 1024 * 1024);
// load up symbols, if any... these may be used for debugging or
// profiling.
@@ -294,17 +299,15 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
debugSymbolTable = NULL;
}
}
+}
- // Set up stack. On Alpha, stack goes below text section. This
- // code should get moved to some architecture-specific spot.
- stack_base = text_base - (409600+4096);
-
- // Set up region for mmaps. Tru64 seems to start just above 0 and
- // grow up from there.
- mmap_start = mmap_end = 0x10000;
+void
+LiveProcess::startup()
+{
+ Process::startup();
- // Set pointer for next thread stack. Reserve 8M for main stack.
- next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+ // load object file into target memory
+ objFile->loadSections(initVirtMem);
// Calculate how much space we need for arg & env arrays.
int argv_array_size = sizeof(Addr) * (argv.size() + 1);
@@ -329,6 +332,9 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
// align it
stack_min &= ~7;
stack_size = stack_base - stack_min;
+ // map memory
+ pTable->allocate(roundDown(stack_min, VMPageSize),
+ roundUp(stack_size, VMPageSize));
// map out initial stack contents
Addr argv_array_base = stack_min + sizeof(uint64_t); // room for argc
@@ -339,17 +345,19 @@ LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
// write contents to stack
uint64_t argc = argv.size();
argc = htog(argc);
- memory->access(Write, stack_min, &argc, sizeof(uint64_t));
+ initVirtMem->writeBlobFunctional(stack_min, (uint8_t*)&argc, sizeof(uint64_t));
- copyStringArray(argv, argv_array_base, arg_data_base, memory);
- copyStringArray(envp, envp_array_base, env_data_base, memory);
+ copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
+ copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
- init_regs->intRegFile[ArgumentReg0] = argc;
- init_regs->intRegFile[ArgumentReg1] = argv_array_base;
- init_regs->intRegFile[StackPointerReg] = stack_min;
- init_regs->intRegFile[GlobalPointerReg] = objFile->globalPointer();
- init_regs->pc = prog_entry;
- init_regs->npc = prog_entry + sizeof(MachInst);
+ execContexts[0]->setIntReg(ArgumentReg0, argc);
+ execContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
+ execContexts[0]->setIntReg(StackPointerReg, stack_min);
+ execContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer());
+ execContexts[0]->setPC(prog_entry);
+ execContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+
+ num_processes++;
}
void
@@ -367,7 +375,7 @@ LiveProcess::syscall(ExecContext *xc)
}
LiveProcess *
-LiveProcess::create(const string &nm,
+LiveProcess::create(const string &nm, System *system,
int stdin_fd, int stdout_fd, int stderr_fd,
string executable,
vector<string> &argv, vector<string> &envp)
@@ -379,12 +387,10 @@ LiveProcess::create(const string &nm,
}
// set up syscall emulation pointer for the current ISA
- process = createProcess(nm, objFile,
+ process = createProcess(nm, objFile, system,
stdin_fd, stdout_fd, stderr_fd,
argv, envp);
- delete objFile;
-
if (process == NULL)
fatal("Unknown error creating process object.");
@@ -400,6 +406,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
Param<string> input;
Param<string> output;
VectorParam<string> env;
+ SimObjectParam<System *> system;
END_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
@@ -410,7 +417,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LiveProcess)
INIT_PARAM(executable, "executable (overrides cmd[0] if set)"),
INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"),
INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"),
- INIT_PARAM(env, "environment settings")
+ INIT_PARAM(env, "environment settings"),
+ INIT_PARAM(system, "system")
END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
@@ -437,7 +445,7 @@ CREATE_SIM_OBJECT(LiveProcess)
stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
- return LiveProcess::create(getInstanceName(),
+ return LiveProcess::create(getInstanceName(), system,
stdin_fd, stdout_fd, stderr_fd,
(string)executable == "" ? cmd[0] : executable,
cmd, env);
diff --git a/sim/process.hh b/sim/process.hh
index 3a48f128c..fc600fb06 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -41,15 +41,21 @@
#include <vector>
#include "arch/isa_traits.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
#include "base/statistics.hh"
#include "base/trace.hh"
+#include "mem/memory.hh"
+//#include "mem/mem_interface.hh"
+#include "mem/page_table.hh"
+#include "sim/sim_object.hh"
+#include "sim/stats.hh"
+#include "targetarch/isa_traits.hh"
class CPUExecContext;
class ExecContext;
-class FunctionalMemory;
class SyscallDesc;
+class TranslatingPort;
+class System;
+
class Process : public SimObject
{
protected:
@@ -57,6 +63,10 @@ class Process : public SimObject
typedef TheISA::MachInst MachInst;
public:
+ /// Pointer to object representing the system this process is
+ /// running on.
+ System *system;
+
// have we initialized an execution context from this process? If
// yes, subsequent contexts are assumed to be for dynamically
// created threads and are not initialized.
@@ -76,16 +86,12 @@ class Process : public SimObject
WaitRec(Addr chan, ExecContext *ctx)
: waitChan(chan), waitingContext(ctx)
- {
- }
+ { }
};
// list of all blocked contexts
std::list<WaitRec> waitList;
- RegFile *init_regs; // initial register contents
- CPUExecContext *cpuXC; // XC to hold the init_regs
-
Addr text_base; // text (code) segment base
unsigned text_size; // text (code) size in bytes
@@ -118,6 +124,7 @@ class Process : public SimObject
protected:
// constructor
Process(const std::string &nm,
+ System *_system,
int stdin_fd, // initial I/O descriptors
int stdout_fd,
int stderr_fd);
@@ -126,7 +133,11 @@ class Process : public SimObject
virtual void startup();
protected:
- FunctionalMemory *memory;
+ /// Memory object for initialization (image loading)
+ TranslatingPort *initVirtMem;
+
+ public:
+ PageTable *pTable;
private:
// file descriptor remapping support
@@ -181,8 +192,6 @@ class Process : public SimObject
}
virtual void syscall(ExecContext *xc) = 0;
-
- virtual FunctionalMemory *getMemory() { return memory; }
};
//
@@ -192,16 +201,23 @@ class ObjectFile;
class LiveProcess : public Process
{
protected:
+ ObjectFile *objFile;
+ std::vector<std::string> argv;
+ std::vector<std::string> envp;
+
LiveProcess(const std::string &nm, ObjectFile *objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
+ void startup();
+
public:
// this function is used to create the LiveProcess object, since
// we can't tell which subclass of LiveProcess to use until we
// open and look at the object file.
static LiveProcess *create(const std::string &nm,
+ System *_system,
int stdin_fd, int stdout_fd, int stderr_fd,
std::string executable,
std::vector<std::string> &argv,
diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc
index 00168b025..1d0b3a375 100644
--- a/sim/syscall_emul.cc
+++ b/sim/syscall_emul.cc
@@ -130,7 +130,7 @@ readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
if (bytes_read != -1)
- bufArg.copyOut(xc->getMemPtr());
+ bufArg.copyOut(xc->port);
return bytes_read;
}
@@ -142,7 +142,7 @@ writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
int nbytes = xc->getSyscallArg(2);
BufferArg bufArg(xc->getSyscallArg(1), nbytes);
- bufArg.copyIn(xc->getMemPtr());
+ bufArg.copyIn(xc->port);
int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
@@ -183,7 +183,7 @@ gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
strncpy((char *)name.bufferPtr(), hostname, name_len);
- name.copyOut(xc->getMemPtr());
+ name.copyOut(xc->port);
return 0;
}
@@ -193,7 +193,7 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return (TheISA::IntReg)-EFAULT;
int result = unlink(path.c_str());
@@ -205,12 +205,12 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string old_name;
- if (xc->getMemPtr()->readString(old_name, xc->getSyscallArg(0)) != NoFault)
+ if (xc->port->readStringFunctional(old_name, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
string new_name;
- if (xc->getMemPtr()->readString(new_name, xc->getSyscallArg(1)) != NoFault)
+ if (xc->port->readStringFunctional(new_name, xc->getSyscallArg(1)) != NoFault)
return -EFAULT;
int64_t result = rename(old_name.c_str(), new_name.c_str());
@@ -222,7 +222,7 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
off_t length = xc->getSyscallArg(1);
@@ -250,7 +250,7 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
/* XXX endianess */
diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh
index 35129bcb4..25f8c6cb8 100644
--- a/sim/syscall_emul.hh
+++ b/sim/syscall_emul.hh
@@ -46,11 +46,12 @@
#include <sys/uio.h>
#include "base/intmath.hh" // for RoundUp
-#include "mem/functional/functional.hh"
+#include "mem/translating_port.hh"
#include "arch/isa_traits.hh" // for Addr
#include "base/trace.hh"
#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
#include "sim/process.hh"
///
@@ -106,18 +107,18 @@ class BaseBufferArg {
//
// copy data into simulator space (read from target memory)
//
- virtual bool copyIn(FunctionalMemory *mem)
+ virtual bool copyIn(TranslatingPort *memport)
{
- mem->access(Read, addr, bufPtr, size);
+ memport->readBlobFunctional(addr, bufPtr, size);
return true; // no EFAULT detection for now
}
//
// copy data out of simulator space (write to target memory)
//
- virtual bool copyOut(FunctionalMemory *mem)
+ virtual bool copyOut(TranslatingPort *memport)
{
- mem->access(Write, addr, bufPtr, size);
+ memport->writeBlobFunctional(addr, bufPtr, size);
return true; // no EFAULT detection for now
}
@@ -369,7 +370,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
if (path == "/dev/sysdev0") {
@@ -416,7 +417,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
uint32_t mode = xc->getSyscallArg(1);
@@ -469,8 +470,8 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
+ return -EFAULT;
struct stat hostBuf;
int result = stat(path.c_str(), &hostBuf);
@@ -478,7 +479,7 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -507,7 +508,7 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStat64Buf(xc->getMemPtr(), fd, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->port, fd, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -521,8 +522,8 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
+ return -EFAULT;
struct stat hostBuf;
int result = lstat(path.c_str(), &hostBuf);
@@ -530,7 +531,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -543,8 +544,8 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
+ return -EFAULT;
#if BSD_HOST
struct stat hostBuf;
@@ -557,7 +558,7 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStat64Buf(xc->getMemPtr(), -1, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->port, -1, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -581,7 +582,8 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
+
return 0;
}
@@ -594,8 +596,8 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
+ return -EFAULT;
struct statfs hostBuf;
int result = statfs(path.c_str(), &hostBuf);
@@ -603,7 +605,7 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -626,7 +628,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
if (result < 0)
return -errno;
- OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf);
return 0;
}
@@ -650,12 +652,12 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process,
for (int i = 0; i < count; ++i)
{
typename OS::tgt_iovec tiov;
- xc->getMemPtr()->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec),
+ xc->port->readBlobFunctional(tiov_base + i*sizeof(typename OS::tgt_iovec),(uint8_t*)
&tiov, sizeof(typename OS::tgt_iovec));
hiov[i].iov_len = gtoh(tiov.iov_len);
hiov[i].iov_base = new char [hiov[i].iov_len];
- xc->getMemPtr()->access(Read, gtoh(tiov.iov_base),
- hiov[i].iov_base, hiov[i].iov_len);
+ xc->port->readBlobFunctional(gtoh(tiov.iov_base),
+ (uint8_t *)hiov[i].iov_base, hiov[i].iov_len);
}
int result = writev(process->sim_fd(fd), hiov, count);
@@ -737,7 +739,7 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
break;
}
- rlp.copyOut(xc->getMemPtr());
+ rlp.copyOut(xc->port);
return 0;
}
@@ -754,7 +756,7 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
tp->tv_sec = htog(tp->tv_sec);
tp->tv_usec = htog(tp->tv_usec);
- tp.copyOut(xc->getMemPtr());
+ tp.copyOut(xc->port);
return 0;
}
@@ -768,11 +770,11 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
{
std::string path;
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
+ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault)
+ return -EFAULT;
TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
- tp.copyIn(xc->getMemPtr());
+ tp.copyIn(xc->port);
struct timeval hostTimeval[2];
for (int i = 0; i < 2; ++i)
@@ -824,7 +826,7 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
rup->ru_nvcsw = 0;
rup->ru_nivcsw = 0;
- rup.copyOut(xc->getMemPtr());
+ rup.copyOut(xc->port);
return 0;
}
diff --git a/sim/system.cc b/sim/system.cc
index 8820922c1..3ed7ed590 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -1,16 +1,19 @@
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
-#include "base/remote_gdb.hh"
#include "cpu/exec_context.hh"
-#include "kern/kernel_stats.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
#include "arch/vtophys.hh"
+#include "mem/memory.hh"
#include "sim/builder.hh"
#include "arch/isa_traits.hh"
#include "sim/byteswap.hh"
#include "sim/system.hh"
#include "base/trace.hh"
+#if FULL_SYSTEM
+#include "base/remote_gdb.hh"
+#include "kern/kernel_stats.hh"
+#include "mem/functional/memory_control.hh"
+#include "targetarch/vtophys.hh"
+#endif
using namespace std;
using namespace TheISA;
@@ -20,12 +23,18 @@ vector<System *> System::systemList;
int System::numSystemsRunning = 0;
System::System(Params *p)
- : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem),
- init_param(p->init_param), numcpus(0), _params(p)
+ : SimObject(p->name), physmem(p->physmem), numcpus(0),
+#if FULL_SYSTEM
+ memctrl(p->memctrl), init_param(p->init_param),
+#else
+ page_ptr(0),
+#endif
+ _params(p)
{
// add self to global system list
systemList.push_back(this);
+#if FULL_SYSTEM
kernelSymtab = new SymbolTable;
debugSymbolTable = new SymbolTable;
@@ -63,25 +72,34 @@ System::System(Params *p)
DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
DPRINTF(Loader, "Kernel loaded...\n");
+#if FULL_SYSTEM
+ kernelBinning = new Kernel::Binning(this);
+#endif // FULL_SYSTEM
+
// increment the number of running systms
numSystemsRunning++;
-
- kernelBinning = new Kernel::Binning(this);
}
System::~System()
{
+#if FULL_SYSTEM
delete kernelSymtab;
delete kernel;
delete kernelBinning;
+#else
+ panic("System::fixFuncEventAddr needs to be rewritten "
+ "to work with syscall emulation");
+#endif // FULL_SYSTEM}
}
-
+#if FULL_SYSTEM
int rgdb_wait = -1;
+#endif // FULL_SYSTEM
+
int
System::registerExecContext(ExecContext *xc, int id)
{
@@ -101,6 +119,7 @@ System::registerExecContext(ExecContext *xc, int id)
execContexts[id] = xc;
numcpus++;
+#if FULL_SYSTEM
RemoteGDB *rgdb = new RemoteGDB(this, xc);
GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
gdbl->listen();
@@ -116,6 +135,7 @@ System::registerExecContext(ExecContext *xc, int id)
}
remoteGDB[id] = rgdb;
+#endif // FULL_SYSTEM
return id;
}
@@ -137,30 +157,48 @@ System::replaceExecContext(ExecContext *xc, int id)
}
execContexts[id] = xc;
+#if FULL_SYSTEM
remoteGDB[id]->replaceExecContext(xc);
+#endif // FULL_SYSTEM
+}
+
+#if !FULL_SYSTEM
+Addr
+System::new_page()
+{
+ Addr return_addr = page_ptr << LogVMPageSize;
+ ++page_ptr;
+ return return_addr;
}
+#endif
void
System::regStats()
{
+#if FULL_SYSTEM
kernelBinning->regStats(name() + ".kern");
+#endif // FULL_SYSTEM
}
void
System::serialize(ostream &os)
{
+#if FULL_SYSTEM
kernelBinning->serialize(os);
kernelSymtab->serialize("kernel_symtab", os);
+#endif // FULL_SYSTEM
}
void
System::unserialize(Checkpoint *cp, const string &section)
{
+#if FULL_SYSTEM
kernelBinning->unserialize(cp, section);
kernelSymtab->unserialize("kernel_symtab", cp, section);
+#endif // FULL_SYSTEM
}
void
diff --git a/sim/system.hh b/sim/system.hh
index ea482a102..cbe876c42 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -35,27 +35,29 @@
#include "base/statistics.hh"
#include "base/loader/symtab.hh"
#include "cpu/pc_event.hh"
-#include "kern/system_events.hh"
#include "sim/sim_object.hh"
+#if FULL_SYSTEM
+#include "kern/system_events.hh"
+#endif
class BaseCPU;
class ExecContext;
-class GDBListener;
class MemoryController;
class ObjectFile;
-class PhysicalMemory;
+class Memory;
+
+#if FULL_SYSTEM
class Platform;
+class GDBListener;
class RemoteGDB;
namespace Kernel { class Binning; }
+#endif
class System : public SimObject
{
public:
- MemoryController *memctrl;
- PhysicalMemory *physmem;
- Platform *platform;
+ Memory *physmem;
PCEventQueue pcEventQueue;
- uint64_t init_param;
std::vector<ExecContext *> execContexts;
int numcpus;
@@ -68,6 +70,11 @@ class System : public SimObject
return numcpus;
}
+#if FULL_SYSTEM
+ MemoryController *memctrl;
+ Platform *platform;
+ uint64_t init_param;
+
/** kernel symbol table */
SymbolTable *kernelSymtab;
@@ -85,6 +92,13 @@ class System : public SimObject
Kernel::Binning *kernelBinning;
+#else
+
+ int page_ptr;
+
+
+#endif // FULL_SYSTEM
+
protected:
/**
@@ -111,6 +125,7 @@ class System : public SimObject
return NULL;
}
+#if FULL_SYSTEM
/** Add a function-based event to kernel code. */
template <class T>
T *System::addKernelFuncEvent(const char *lbl)
@@ -118,18 +133,23 @@ class System : public SimObject
return addFuncEvent<T>(kernelSymtab, lbl);
}
+#endif
public:
+#if FULL_SYSTEM
std::vector<RemoteGDB *> remoteGDB;
std::vector<GDBListener *> gdbListen;
virtual bool breakpoint() = 0;
+#endif // FULL_SYSTEM
public:
struct Params
{
std::string name;
+ Memory *physmem;
+
+#if FULL_SYSTEM
Tick boot_cpu_frequency;
MemoryController *memctrl;
- PhysicalMemory *physmem;
uint64_t init_param;
bool bin;
std::vector<std::string> binned_fns;
@@ -137,6 +157,7 @@ class System : public SimObject
std::string kernel_path;
std::string readfile;
+#endif
};
protected:
@@ -151,6 +172,8 @@ class System : public SimObject
const Params *params() const { return (const Params *)_params; }
public:
+
+#if FULL_SYSTEM
/**
* Returns the addess the kernel starts at.
* @return address the kernel starts at
@@ -169,6 +192,12 @@ class System : public SimObject
*/
Addr getKernelEntry() const { return kernelEntry; }
+#else
+
+ Addr new_page();
+
+#endif // FULL_SYSTEM
+
int registerExecContext(ExecContext *xc, int xcIndex);
void replaceExecContext(ExecContext *xc, int xcIndex);