diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/base.hh | 8 | ||||
-rw-r--r-- | cpu/exec_context.cc | 6 | ||||
-rw-r--r-- | cpu/exec_context.hh | 4 | ||||
-rw-r--r-- | cpu/simple/cpu.cc | 210 | ||||
-rw-r--r-- | cpu/simple/cpu.hh | 26 |
5 files changed, 166 insertions, 88 deletions
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(®s, 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(); |