diff options
Diffstat (limited to 'cpu/simple/cpu.cc')
-rw-r--r-- | cpu/simple/cpu.cc | 213 |
1 files changed, 119 insertions, 94 deletions
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index d8d4c3644..fc70df662 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -44,6 +44,7 @@ #include "base/stats/events.hh" #include "base/trace.hh" #include "cpu/base.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" #include "cpu/exetrace.hh" #include "cpu/profile.hh" @@ -52,6 +53,7 @@ #include "cpu/smt.hh" #include "cpu/static_inst.hh" #include "kern/kernel_stats.hh" +#include "sim/byteswap.hh" #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/host.hh" @@ -64,14 +66,16 @@ #include "mem/functional/memory_control.hh" #include "mem/functional/physical.hh" #include "sim/system.hh" -#include "targetarch/alpha_memory.hh" -#include "targetarch/stacktrace.hh" -#include "targetarch/vtophys.hh" +#include "arch/tlb.hh" +#include "arch/stacktrace.hh" +#include "arch/vtophys.hh" #else // !FULL_SYSTEM #include "mem/memory.hh" #endif // FULL_SYSTEM using namespace std; +//The SimpleCPU does alpha only +using namespace AlphaISA; SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) @@ -79,6 +83,21 @@ SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) { } + +void +SimpleCPU::init() +{ + BaseCPU::init(); +#if FULL_SYSTEM + for (int i = 0; i < execContexts.size(); ++i) { + ExecContext *xc = execContexts[i]; + + // initialize CPU, including PC + TheISA::initCPU(xc, xc->readCpuId()); + } +#endif +} + void SimpleCPU::TickEvent::process() { @@ -129,7 +148,7 @@ SimpleCPU::CpuPort::recvRetry() SimpleCPU::SimpleCPU(Params *p) : BaseCPU(p), icachePort(this), - dcachePort(this), tickEvent(this, p->width), xc(NULL) + dcachePort(this), tickEvent(this, p->width), cpuXC(NULL) { _status = Idle; @@ -143,15 +162,14 @@ SimpleCPU::SimpleCPU(Params *p) (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); + cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); #else - xc = new ExecContext(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(); + #if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE ifetch_req = new CpuRequest; ifetch_req->asid = 0; @@ -183,7 +201,7 @@ SimpleCPU::SimpleCPU(Params *p) lastIcacheStall = 0; lastDcacheStall = 0; - execContexts.push_back(xc); + execContexts.push_back(xcProxy); } SimpleCPU::~SimpleCPU() @@ -232,7 +250,7 @@ void SimpleCPU::activateContext(int thread_num, int delay) { assert(thread_num == 0); - assert(xc); + assert(cpuXC); assert(_status == Idle); notIdleFraction++; @@ -245,7 +263,7 @@ void SimpleCPU::suspendContext(int thread_num) { assert(thread_num == 0); - assert(xc); + assert(cpuXC); assert(_status == Running); notIdleFraction--; @@ -338,7 +356,7 @@ SimpleCPU::serialize(ostream &os) SERIALIZE_ENUM(_status); SERIALIZE_SCALAR(inst); nameOut(os, csprintf("%s.xc", name())); - xc->serialize(os); + cpuXC->serialize(os); nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); nameOut(os, csprintf("%s.cacheCompletionEvent", name())); @@ -350,7 +368,7 @@ SimpleCPU::unserialize(Checkpoint *cp, const string §ion) BaseCPU::unserialize(cp, section); UNSERIALIZE_ENUM(_status); UNSERIALIZE_SCALAR(inst); - xc->unserialize(cp, csprintf("%s.xc", section)); + cpuXC->unserialize(cp, csprintf("%s.xc", section)); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); } @@ -371,7 +389,7 @@ SimpleCPU::copySrcTranslate(Addr src) // Make sure block doesn't span page if (no_warn && - (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) && + (src & PageMask) != ((src + blk_size) & PageMask) && (src >> 40) != 0xfffffc) { warn("Copied block source spans pages %x.", src); no_warn = false; @@ -379,17 +397,16 @@ SimpleCPU::copySrcTranslate(Addr src) memReq->reset(src & ~(blk_size - 1), blk_size); - // translate to physical address - Fault fault = xc->translateDataReadReq(req); - - assert(fault != Alignment_Fault); + // translate to physical address Fault fault = cpuXC->translateDataReadReq(req); - if (fault == No_Fault) { - xc->copySrcAddr = src; - xc->copySrcPhysAddr = memReq->paddr + offset; + if (fault == NoFault) { + cpuXC->copySrcAddr = src; + cpuXC->copySrcPhysAddr = memReq->paddr + offset; } else { - xc->copySrcAddr = 0; - xc->copySrcPhysAddr = 0; + assert(!fault->isAlignmentFault()); + + cpuXC->copySrcAddr = 0; + cpuXC->copySrcPhysAddr = 0; } return fault; #else @@ -406,12 +423,12 @@ SimpleCPU::copy(Addr dest) // Only support block sizes of 64 atm. assert(blk_size == 64); uint8_t data[blk_size]; - //assert(xc->copySrcAddr); + //assert(cpuXC->copySrcAddr); int offset = dest & (blk_size - 1); // Make sure block doesn't span page if (no_warn && - (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) && + (dest & PageMask) != ((dest + blk_size) & PageMask) && (dest >> 40) != 0xfffffc) { no_warn = false; warn("Copied block destination spans pages %x. ", dest); @@ -419,21 +436,19 @@ SimpleCPU::copy(Addr dest) memReq->reset(dest & ~(blk_size -1), blk_size); // translate to physical address - Fault fault = xc->translateDataWriteReq(req); - - assert(fault != Alignment_Fault); + Fault fault = cpuXC->translateDataWriteReq(req); - if (fault == No_Fault) { + if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; // Need to read straight from memory since we have more than 8 bytes. - memReq->paddr = xc->copySrcPhysAddr; - xc->mem->read(memReq, data); + memReq->paddr = cpuXC->copySrcPhysAddr; + cpuXC->mem->read(memReq, data); memReq->paddr = dest_addr; - xc->mem->write(memReq, data); + cpuXC->mem->write(memReq, data); if (dcacheInterface) { memReq->cmd = Copy; memReq->completionEvent = NULL; - memReq->paddr = xc->copySrcPhysAddr; + memReq->paddr = cpuXC->copySrcPhysAddr; memReq->dest = dest_addr; memReq->size = 64; memReq->time = curTick; @@ -441,6 +456,9 @@ SimpleCPU::copy(Addr dest) dcacheInterface->access(memReq); } } + else + assert(!fault->isAlignmentFault()); + return fault; #else panic("copy not implemented"); @@ -480,7 +498,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) data_read_req->time = curTick; // translate to physical address - Fault fault = xc->translateDataReadReq(data_read_req); + Fault fault = cpuXC->translateDataReadReq(data_read_req); // Now do the access. if (fault == No_Fault) { @@ -527,13 +545,12 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) _status = DcacheMissStall; } else { // do functional access - fault = xc->read(memReq, data); + fault = cpuXC->read(memReq, data); } - - } else if(fault == No_Fault) { + } else if(fault == NoFault) { // do functional access - fault = xc->read(memReq, data); + fault = cpuXC->read(memReq, data); } */ @@ -597,8 +614,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) data_write_req->flags = flags; // translate to physical address - Fault fault = xc->translateDataWriteReq(data_write_req); - + Fault fault = cpuXC->translateDataWriteReq(data_write_req); // Now do the access. if (fault == No_Fault) { #if SIMPLE_CPU_MEM_TIMING @@ -618,10 +634,10 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) /* // do functional access - if (fault == No_Fault) - fault = xc->write(memReq, data); + if (fault == NoFault) + fault = cpuXC->write(memReq, data); - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { memReq->cmd = Write; memcpy(memReq->data,(uint8_t *)&data,memReq->size); memReq->completionEvent = NULL; @@ -640,7 +656,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) } } */ - if (res && (fault == No_Fault)) + if (res && (fault == NoFault)) *res = data_write_pkt->result; // This will need a new way to tell if it's hooked up to a cache or not. @@ -699,7 +715,7 @@ SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) Addr SimpleCPU::dbg_vtophys(Addr addr) { - return vtophys(xc, addr); + return vtophys(xcProxy, addr); } #endif // FULL_SYSTEM @@ -863,9 +879,9 @@ SimpleCPU::post_interrupt(int int_num, int index) { BaseCPU::post_interrupt(int_num, index); - if (xc->status() == ExecContext::Suspended) { + if (cpuXC->status() == ExecContext::Suspended) { DPRINTF(IPI,"Suspended Processor awoke\n"); - xc->activate(); + cpuXC->activate(); } } #endif // FULL_SYSTEM @@ -878,30 +894,29 @@ SimpleCPU::tick() traceData = NULL; - Fault fault = No_Fault; + Fault fault = NoFault; #if FULL_SYSTEM - if (checkInterrupts && check_interrupts() && !xc->inPalMode() && + if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() && status() != IcacheMissComplete) { int ipl = 0; int summary = 0; checkInterrupts = false; - IntReg *ipr = xc->regs.ipr; - if (xc->regs.ipr[TheISA::IPR_SIRR]) { - for (int i = TheISA::INTLEVEL_SOFTWARE_MIN; - i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) { - if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) { + if (cpuXC->readMiscReg(IPR_SIRR)) { + for (int i = INTLEVEL_SOFTWARE_MIN; + i < INTLEVEL_SOFTWARE_MAX; i++) { + if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference - ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1; + ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); } } } - uint64_t interrupts = xc->cpu->intr_status(); - for (int i = TheISA::INTLEVEL_EXTERNAL_MIN; - i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) { + uint64_t interrupts = cpuXC->cpu->intr_status(); + for (int i = INTLEVEL_EXTERNAL_MIN; + i < INTLEVEL_EXTERNAL_MAX; i++) { if (interrupts & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference ipl = i; @@ -909,24 +924,25 @@ SimpleCPU::tick() } } - if (ipr[TheISA::IPR_ASTRR]) + if (cpuXC->readMiscReg(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) { - ipr[TheISA::IPR_ISR] = summary; - ipr[TheISA::IPR_INTID] = ipl; - xc->ev5_trap(Interrupt_Fault); + if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) { + cpuXC->setMiscReg(IPR_ISR, summary); + cpuXC->setMiscReg(IPR_INTID, ipl); + + Fault(new InterruptFault)->invoke(xcProxy); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - ipr[TheISA::IPR_IPLR], ipl, summary); + cpuXC->readMiscReg(IPR_IPLR), ipl, summary); } } #endif // maintain $r0 semantics - xc->regs.intRegFile[ZeroReg] = 0; + cpuXC->setIntReg(ZeroReg, 0); #ifdef TARGET_ALPHA - xc->regs.floatRegFile.d[ZeroReg] = 0.0; + cpuXC->setFloatRegDouble(ZeroReg, 0.0); #endif // TARGET_ALPHA if (status() == IcacheAccessComplete) { @@ -951,7 +967,7 @@ SimpleCPU::tick() ifetch_req->size = sizeof(MachInst); #endif - ifetch_req->vaddr = xc->regs.pc & ~3; + ifetch_req->vaddr = cpuXC->readPC() & ~3; ifetch_req->time = curTick; /* memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t), @@ -960,7 +976,7 @@ SimpleCPU::tick() fault = xc->translateInstReq(ifetch_req); - if (fault == No_Fault) { + if (fault == NoFault) { #if SIMPLE_CPU_MEM_TIMING Packet *ifetch_pkt = new Packet; ifetch_pkt->cmd = Read; @@ -975,7 +991,7 @@ SimpleCPU::tick() return; #endif /* - if (icacheInterface && fault == No_Fault) { + if (icacheInterface && fault == NoFault) { memReq->completionEvent = NULL; memReq->time = curTick; @@ -999,7 +1015,7 @@ SimpleCPU::tick() // If we've got a valid instruction (i.e., no fault on instruction // fetch), then execute it. - if (fault == No_Fault) { + if (fault == NoFault) { // keep an instruction count numInst++; @@ -1010,31 +1026,32 @@ SimpleCPU::tick() // decode the instruction inst = gtoh(inst); - curStaticInst = StaticInst<TheISA>::decode(inst); + curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC())); - traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst, - xc->regs.pc); + traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst, + cpuXC->readPC()); #if FULL_SYSTEM - xc->setInst(inst); + cpuXC->setInst(inst); #endif // FULL_SYSTEM - xc->func_exe_inst++; + cpuXC->func_exe_inst++; fault = curStaticInst->execute(this, traceData); #if FULL_SYSTEM - if (xc->fnbin) { - assert(xc->kernelStats); - system->kernelBinning->execute(xc, inst); + if (system->kernelBinning->fnbin) { + assert(kernelStats); + system->kernelBinning->execute(xcProxy, inst); } - if (xc->profile) { - bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; - xc->profilePC = usermode ? 1 : xc->regs.pc; - ProfileNode *node = xc->profile->consume(xc, inst); + if (cpuXC->profile) { + bool usermode = + (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + cpuXC->profilePC = usermode ? 1 : cpuXC->readPC(); + ProfileNode *node = cpuXC->profile->consume(xcProxy, inst); if (node) - xc->profileNode = node; + cpuXC->profileNode = node; } #endif @@ -1053,29 +1070,37 @@ SimpleCPU::tick() traceData->finalize(); } - traceFunctions(xc->regs.pc); + traceFunctions(cpuXC->readPC()); - } // if (fault == No_Fault) + } // if (fault == NoFault) - if (fault != No_Fault) { + if (fault != NoFault) { #if FULL_SYSTEM - xc->ev5_trap(fault); + fault->invoke(xcProxy); #else // !FULL_SYSTEM - fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc); + fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC()); #endif // FULL_SYSTEM } else { +#if THE_ISA != MIPS_ISA // go to the next instruction - xc->regs.pc = xc->regs.npc; - xc->regs.npc += sizeof(MachInst); + cpuXC->setPC(cpuXC->readNextPC()); + cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); +#else + // go to the next instruction + cpuXC->setPC(cpuXC->readNextPC()); + cpuXC->setNextPC(cpuXC->readNextNPC()); + cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst)); +#endif + } #if FULL_SYSTEM Addr oldpc; do { - oldpc = xc->regs.pc; - system->pcEventQueue.service(xc); - } while (oldpc != xc->regs.pc); + oldpc = cpuXC->readPC(); + system->pcEventQueue.service(xcProxy); + } while (oldpc != cpuXC->readPC()); #endif assert(status() == Running || |