summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/loader/aout_object.cc28
-rw-r--r--base/loader/aout_object.hh1
-rw-r--r--base/loader/ecoff_object.cc27
-rw-r--r--base/loader/ecoff_object.hh1
-rw-r--r--base/loader/elf_object.cc31
-rw-r--r--base/loader/elf_object.hh4
-rw-r--r--base/loader/object_file.cc34
-rw-r--r--base/loader/object_file.hh9
-rw-r--r--cpu/base.hh8
-rw-r--r--cpu/exec_context.cc6
-rw-r--r--cpu/exec_context.hh4
-rw-r--r--cpu/simple/cpu.cc210
-rw-r--r--cpu/simple/cpu.hh26
-rw-r--r--mem/physical.cc2
-rw-r--r--mem/port.cc9
-rw-r--r--mem/translating_port.cc20
-rw-r--r--mem/translating_port.hh3
17 files changed, 243 insertions, 180 deletions
diff --git a/base/loader/aout_object.cc b/base/loader/aout_object.cc
index d1b27120d..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/translating_port.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,30 +80,6 @@ AoutObject::AoutObject(const string &_filename, int _fd,
bool
-AoutObject::loadSections(TranslatingPort *memPort, 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)
- memPort->writeBlobFunctional(textAddr, fileData + N_TXTOFF(*execHdr),
- text.size, true);
- if (data.size != 0)
- memPort->writeBlobFunctional(dataAddr, fileData + N_DATOFF(*execHdr),
- data.size, true);
-
- 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 359866dc5..aeb710427 100644
--- a/base/loader/aout_object.hh
+++ b/base/loader/aout_object.hh
@@ -46,7 +46,6 @@ class AoutObject : public ObjectFile
public:
virtual ~AoutObject() {}
- virtual bool loadSections(TranslatingPort *memPort, 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 a4b8c8713..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/translating_port.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,28 +83,6 @@ EcoffObject::EcoffObject(const string &_filename, int _fd,
bool
-EcoffObject::loadSections(TranslatingPort *memPort, 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.
- memPort->writeBlobFunctional(textAddr, fileData + ECOFF_TXTOFF(execHdr),
- text.size, true);
- memPort->writeBlobFunctional(dataAddr, fileData + ECOFF_DATOFF(execHdr),
- data.size, true);
-
- return true;
-}
-
-
-bool
EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
{
if (!symtab)
diff --git a/base/loader/ecoff_object.hh b/base/loader/ecoff_object.hh
index 39b161bfc..603c70bec 100644
--- a/base/loader/ecoff_object.hh
+++ b/base/loader/ecoff_object.hh
@@ -50,7 +50,6 @@ class EcoffObject : public ObjectFile
public:
virtual ~EcoffObject() {}
- virtual bool loadSections(TranslatingPort *memPort, 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 11c94d651..52f236fef 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/translating_port.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh" // for DPRINTF
@@ -131,20 +130,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).
@@ -153,6 +151,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;
}
}
@@ -170,28 +169,6 @@ ElfObject::ElfObject(const string &_filename, int _fd,
bool
-ElfObject::loadSections(TranslatingPort *memPort, 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)
- memPort->writeBlobFunctional(textAddr, fileTextBits, text.size, true);
- if (data.size != 0)
- memPort->writeBlobFunctional(dataAddr, fileDataBits, data.size, true);
-
- 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 3e93c30b7..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,7 +45,6 @@ class ElfObject : public ObjectFile
public:
virtual ~ElfObject() {}
- virtual bool loadSections(TranslatingPort *memPort, 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 1d750e341..35ea11b54 100644
--- a/base/loader/object_file.hh
+++ b/base/loader/object_file.hh
@@ -67,7 +67,7 @@ class ObjectFile
void close();
- virtual bool loadSections(TranslatingPort *memPort, bool loadPhys = false) = 0;
+ virtual bool loadSections(TranslatingPort *memPort, bool loadPhys = false);
virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
@@ -77,8 +77,9 @@ class ObjectFile
protected:
struct Section {
- Addr baseAddr;
- size_t size;
+ Addr baseAddr;
+ uint8_t *fileImage;
+ size_t size;
};
Addr entry;
@@ -88,6 +89,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/cpu/base.hh b/cpu/base.hh
index 870e26a39..c0e087f42 100644
--- a/cpu/base.hh
+++ b/cpu/base.hh
@@ -155,14 +155,6 @@ class BaseCPU : public SimObject
int number_of_threads;
/**
- * A pointer to the port into the memory system to be used by syscall
- * emulation. This way the data being accessed via syscalls looks in
- * the memory heirachy for any changes that haven't been written back
- * to main memory yet.
- */
- Port* memPort;
-
- /**
* Vector of per-thread instruction-based event queues. Used for
* scheduling events based on number of instructions committed by
* a particular thread.
diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc
index fa91eb672..0b91992cf 100644
--- a/cpu/exec_context.cc
+++ b/cpu/exec_context.cc
@@ -37,13 +37,13 @@
#include "base/output.hh"
#include "cpu/profile.hh"
#include "kern/kernel_stats.hh"
-#include "mem/translating_port.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
#include "targetarch/stacktrace.hh"
#else
#include "sim/process.hh"
+#include "mem/translating_port.hh"
#endif
using namespace std;
@@ -78,14 +78,14 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
}
#else
ExecContext::ExecContext(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),
process(_process),
asid(_asid),
func_exe_inst(0), storeCondFailures(0)
{
- port = new TranslatingPort(cpu->memPort, process->pTable);
+ port = new TranslatingPort(mem_port, process->pTable);
memset(&regs, 0, sizeof(RegFile));
}
#endif
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index 8e9e5f2fd..f55b45de1 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -35,7 +35,6 @@
#include "sim/host.hh"
#include "sim/serialize.hh"
#include "targetarch/byte_swap.hh"
-#include "mem/translating_port.hh"
class BaseCPU;
@@ -52,6 +51,7 @@ namespace Kernel { class Binning; class Statistics; }
#else // !FULL_SYSTEM
#include "sim/process.hh"
+class TranslatingPort;
#endif // FULL_SYSTEM
@@ -187,7 +187,7 @@ class ExecContext
AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
#else
ExecContext(BaseCPU *_cpu, int _thread_num,
- Process *_process, int _asid);
+ Process *_process, int _asid, Port *mem_port);
#endif
virtual ~ExecContext();
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc
index 41acd2456..d8d4c3644 100644
--- a/cpu/simple/cpu.cc
+++ b/cpu/simple/cpu.cc
@@ -132,16 +132,6 @@ SimpleCPU::SimpleCPU(Params *p)
dcachePort(this), tickEvent(this, p->width), xc(NULL)
{
_status = Idle;
-#if FULL_SYSTEM
- xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
-
- // initialize CPU, including PC
- TheISA::initCPU(&xc->regs);
-#else
- xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0);
-#endif // !FULL_SYSTEM
-
- memPort = &dcachePort;
//Create Memory Ports (conect them up)
p->mem->addPort("DCACHE");
@@ -152,11 +142,39 @@ SimpleCPU::SimpleCPU(Params *p)
icachePort.setPeer(p->mem->getPort("ICACHE"));
(p->mem->getPort("ICACHE"))->setPeer(&icachePort);
+#if FULL_SYSTEM
+ xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
+ // initialize CPU, including PC
+ TheISA::initCPU(&xc->regs);
+#else
+ xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0,
+ &dcachePort);
+#endif // !FULL_SYSTEM
- req = new CpuRequest;
-
- req->asid = 0;
+#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;
@@ -425,6 +443,7 @@ SimpleCPU::copy(Addr dest)
}
return fault;
#else
+ panic("copy not implemented");
return No_Fault;
#endif
}
@@ -437,8 +456,8 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
if (status() == DcacheWaitResponse || status() == DcacheWaitSwitch) {
// Fault fault = xc->read(memReq,data);
// Not sure what to check for no fault...
- if (pkt->result == Success) {
- memcpy(&data, pkt->data, sizeof(T));
+ if (data_read_pkt->result == Success) {
+ memcpy(&data, data_read_pkt->data, sizeof(T));
}
if (traceData) {
@@ -451,19 +470,45 @@ SimpleCPU::read(Addr addr, T &data, unsigned 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
- // NEED NEW TRANSLATION HERE
- Fault fault = xc->translateDataReadReq(req);
+ Fault fault = xc->translateDataReadReq(data_read_req);
// Now do the access.
if (fault == No_Fault) {
- pkt = new Packet;
- pkt->cmd = Read;
- req->paddr = addr;
- pkt->size = sizeof(T);
- pkt->req = req;
+#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);
+
+ sendDcacheRequest(data_read_pkt);
+
+#if SIMPLE_CPU_MEM_IMMEDIATE
+ // Need to find a way to not duplicate code above.
- sendDcacheRequest();
+ 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;
@@ -493,7 +538,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
}
*/
// This will need a new way to tell if it has a dcache attached.
- if (/*!dcacheInterface && */(req->flags & UNCACHEABLE))
+ if (data_read_req->flags & UNCACHEABLE)
recordEvent("Uncached Read");
return fault;
@@ -546,27 +591,29 @@ template <class T>
Fault
SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
-// memReq->reset(addr, sizeof(T), flags);
- req->vaddr = addr;
- req->time = curTick;
- req->size = sizeof(T);
+ 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
- // NEED NEW TRANSLATION HERE
- Fault fault = xc->translateDataWriteReq(req);
+ Fault fault = xc->translateDataWriteReq(data_write_req);
// Now do the access.
if (fault == No_Fault) {
- pkt = new Packet;
- pkt->cmd = Write;
- pkt->size = sizeof(T);
- pkt->req = req;
-
- // Copy data into the packet.
- pkt->data = new uint8_t[64];
- memcpy(pkt->data, &data, sizeof(T));
+#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();
+ sendDcacheRequest(data_write_pkt);
}
/*
@@ -594,10 +641,10 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
}
*/
if (res && (fault == No_Fault))
- *res = pkt->result;
+ *res = data_write_pkt->result;
// This will need a new way to tell if it's hooked up to a cache or not.
- if (/*!dcacheInterface && */(req->flags & UNCACHEABLE))
+ if (data_write_req->flags & UNCACHEABLE)
recordEvent("Uncached Write");
// If the write needs to have a fault on the access, consider calling
@@ -657,9 +704,11 @@ SimpleCPU::dbg_vtophys(Addr addr)
#endif // FULL_SYSTEM
void
-SimpleCPU::sendIcacheRequest()
+SimpleCPU::sendIcacheRequest(Packet *pkt)
{
-#if 0
+ assert(!tickEvent.scheduled());
+#if SIMPLE_CPU_MEM_TIMING
+ retry_pkt = pkt;
bool success = icachePort.sendTiming(*pkt);
unscheduleTickEvent();
@@ -673,7 +722,7 @@ SimpleCPU::sendIcacheRequest()
// Need to wait for cache to respond
_status = IcacheWaitResponse;
}
-#else
+#elif SIMPLE_CPU_MEM_ATOMIC
Tick latency = icachePort.sendAtomic(*pkt);
unscheduleTickEvent();
@@ -685,17 +734,21 @@ SimpleCPU::sendIcacheRequest()
icacheStallCycles += latency;
_status = IcacheAccessComplete;
-
- delete pkt;
+#elif SIMPLE_CPU_MEM_IMMEDIATE
+ icachePort.sendAtomic(*pkt);
+#else
+#error "SimpleCPU has no mem model set"
#endif
}
void
-SimpleCPU::sendDcacheRequest()
+SimpleCPU::sendDcacheRequest(Packet *pkt)
{
+ assert(!tickEvent.scheduled());
+#if SIMPLE_CPU_MEM_TIMING
unscheduleTickEvent();
-#if 0
+ retry_pkt = pkt;
bool success = dcachePort.sendTiming(*pkt);
lastDcacheStall = curTick;
@@ -705,7 +758,9 @@ SimpleCPU::sendDcacheRequest()
} else {
_status = DcacheWaitResponse;
}
-#else
+#elif SIMPLE_CPU_MEM_ATOMIC
+ unscheduleTickEvent();
+
Tick latency = dcachePort.sendAtomic(*pkt);
scheduleTickEvent(latency);
@@ -714,19 +769,22 @@ SimpleCPU::sendDcacheRequest()
// 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;
-
- // Delete the packet right here?
- delete pkt;
+#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.
- pkt = &response;
+ Packet *pkt = &response;
switch (status()) {
case IcacheWaitResponse:
@@ -780,19 +838,23 @@ SimpleCPU::processResponse(Packet &response)
Packet *
SimpleCPU::processRetry()
{
+#if SIMPLE_CPU_MEM_TIMING
switch(status()) {
case IcacheRetry:
icacheRetryCycles += curTick - lastIcacheStall;
- return pkt;
+ return retry_pkt;
break;
case DcacheRetry:
dcacheRetryCycles += curTick - lastDcacheStall;
- return pkt;
+ return retry_pkt;
break;
default:
panic("SimpleCPU::processRetry: bad state");
break;
}
+#else
+ panic("shouldn't be here");
+#endif
}
#if FULL_SYSTEM
@@ -884,28 +946,35 @@ SimpleCPU::tick()
#define IFETCH_FLAGS(pc) 0
#endif
- req->vaddr = xc->regs.pc & ~3;
- req->time = curTick;
- req->size = sizeof(MachInst);
+#if SIMPLE_CPU_MEM_TIMING
+ CpuRequest *ifetch_req = new CpuRequest();
+ ifetch_req->size = sizeof(MachInst);
+#endif
+
+ ifetch_req->vaddr = xc->regs.pc & ~3;
+ ifetch_req->time = curTick;
/* memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t),
IFETCH_FLAGS(xc->regs.pc));
*/
- fault = xc->translateInstReq(req);
+ fault = xc->translateInstReq(ifetch_req);
if (fault == No_Fault) {
- pkt = new Packet;
- pkt->cmd = Read;
- pkt->addr = req->paddr;
- pkt->size = sizeof(MachInst);
- pkt->req = req;
- pkt->data = (uint8_t *)&inst;
-
- sendIcacheRequest();
- return;
-/* fault = xc->mem->read(memReq, inst);
+#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 == No_Fault) {
memReq->completionEvent = NULL;
@@ -980,8 +1049,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() == DcacheWaitResponse && pkt->cmd == Read)) {
+ if (traceData && (status() != DcacheWaitResponse)) {
traceData->finalize();
}
diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh
index 3354166cc..ca10134f7 100644
--- a/cpu/simple/cpu.hh
+++ b/cpu/simple/cpu.hh
@@ -64,6 +64,16 @@ 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
{
class CpuPort : public Port
@@ -188,8 +198,16 @@ class SimpleCPU : public BaseCPU
// current instruction
MachInst inst;
- CpuRequest *req;
- Packet *pkt;
+#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
@@ -246,8 +264,8 @@ class SimpleCPU : public BaseCPU
Stats::Scalar<> dcacheRetryCycles;
Counter lastDcacheRetry;
- void sendIcacheRequest();
- void sendDcacheRequest();
+ void sendIcacheRequest(Packet *pkt);
+ void sendDcacheRequest(Packet *pkt);
void processResponse(Packet &response);
Packet * processRetry();
diff --git a/mem/physical.cc b/mem/physical.cc
index fea4b6ec5..69544c8fe 100644
--- a/mem/physical.cc
+++ b/mem/physical.cc
@@ -174,6 +174,8 @@ PhysicalMemory::doFunctionalAccess(Packet &pkt)
default:
panic("unimplemented");
}
+
+ pkt.result = Success;
}
Port *
diff --git a/mem/port.cc b/mem/port.cc
index 8c4b3810c..e080f8b81 100644
--- a/mem/port.cc
+++ b/mem/port.cc
@@ -63,3 +63,12 @@ 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);
+}
diff --git a/mem/translating_port.cc b/mem/translating_port.cc
index e385a74b6..f4f2ca737 100644
--- a/mem/translating_port.cc
+++ b/mem/translating_port.cc
@@ -83,23 +83,31 @@ TranslatingPort::writeBlobFunctional(Addr addr, uint8_t *p, int size,
return No_Fault;
}
-/*
+
Fault
-TranslatingPort::memsetBlobFunctional(Addr addr, uint8_t val, int size)
+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))
- return Machine_Check_Fault;
+ 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());
+ port->memsetBlobFunctional(paddr, val, gen.size());
}
return No_Fault;
}
-*/
+
Fault
TranslatingPort::writeStringFunctional(Addr addr, const char *str)
diff --git a/mem/translating_port.hh b/mem/translating_port.hh
index 3d77b2c2b..1a334c103 100644
--- a/mem/translating_port.hh
+++ b/mem/translating_port.hh
@@ -51,7 +51,8 @@ class TranslatingPort
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);
+ 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);