Simple program runs with sendAtomic!

Ignoring returned latency for now.
Refactored loadSections in ObjectFile hierarchy.

base/loader/aout_object.cc:
base/loader/aout_object.hh:
base/loader/ecoff_object.cc:
base/loader/ecoff_object.hh:
base/loader/elf_object.cc:
base/loader/elf_object.hh:
base/loader/object_file.hh:
    Have each section record a pointer to image data.
    This allows us to move common loadSections code into ObjectFile.
base/loader/object_file.cc:
    Have each section record a pointer to image data.
    This allows us to move common loadSections code into ObjectFile.
    Also explicitly load BSS now since we need to allocate the
    translations for it in syscall emulation.
cpu/base.hh:
    Don't need memPort (just pass port in to ExecContext constructor).
cpu/exec_context.cc:
cpu/exec_context.hh:
mem/port.cc:
mem/translating_port.cc:
mem/translating_port.hh:
    Pass syscall emulation Port into constructor instead of
    getting it from BaseCPU.
cpu/simple/cpu.cc:
    Explicitly choose one of three timing models.
    Statically allocate request and packet objects when possible.
    Several more minor bug fixes.
    Works for simple program with SIMPLE_CPU_MEM_IMMEDIATE model now.
    Probably have memory leaks with SIMPLE_CPU_MEM_TIMING (if it works at all).
    Pass syscall emulation Port into constructor instead of
    getting it from BaseCPU.
cpu/simple/cpu.hh:
    Explicitly choose one of three timing models.
    Statically allocate request and packet objects when possible.
    Pass syscall emulation Port into constructor instead of
    getting it from BaseCPU.
mem/physical.cc:
    Set packet result field.

--HG--
extra : convert_revision : 359d0ebe4b4665867f4e26e7394ec0f1d17cfc26
This commit is contained in:
Steve Reinhardt 2006-03-02 10:31:48 -05:00
parent 0c2c7171a8
commit e7f442d527
17 changed files with 241 additions and 178 deletions

View file

@ -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,
@ -77,30 +79,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)
{

View file

@ -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);

View file

@ -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,
@ -81,28 +82,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)
{

View file

@ -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);

View file

@ -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;
}
}
@ -169,28 +168,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)
{

View file

@ -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);

View file

@ -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()
{

View file

@ -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; }

View file

@ -154,14 +154,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

View file

@ -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

View file

@ -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();

View file

@ -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;
#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);
req->asid = 0;
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();
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;
@ -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;
#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);
// Copy data into the packet.
pkt->data = new uint8_t[64];
memcpy(pkt->data, &data, 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;
#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();
sendIcacheRequest(ifetch_pkt);
#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC
return;
/* fault = xc->mem->read(memReq, inst);
#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();
}

View file

@ -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();

View file

@ -174,6 +174,8 @@ PhysicalMemory::doFunctionalAccess(Packet &pkt)
default:
panic("unimplemented");
}
pkt.result = Success;
}
Port *

View file

@ -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);
}

View file

@ -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)

View file

@ -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);