From: Gabe Black Date: Wed, 1 Feb 2012 06:40:08 +0000 (-0800) Subject: Merge with head, hopefully the last time for this batch. X-Git-Tag: stable_2012_06_28~264 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ea8b347dc5d375572d8d19770024ec8be5fd5017;p=gem5.git Merge ... head, hopefully the last time for this batch. --- ea8b347dc5d375572d8d19770024ec8be5fd5017 diff --cc src/arch/arm/insts/static_inst.hh index d65555822,5af97b796..c36024ecd --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@@ -46,7 -46,7 +46,8 @@@ #include "arch/arm/utility.hh" #include "base/trace.hh" #include "cpu/static_inst.hh" + #include "sim/byteswap.hh" +#include "sim/full_system.hh" namespace ArmISA { diff --cc src/arch/arm/isa/formats/m5ops.isa index 3b08acad7,534d12cd9..1eb7d3f65 --- a/src/arch/arm/isa/formats/m5ops.isa +++ b/src/arch/arm/isa/formats/m5ops.isa @@@ -59,10 -63,15 +59,11 @@@ def format M5ops() { case 0x41: return new Dumpstats(machInst); case 0x42: return new Dumpresetstats(machInst); case 0x43: return new M5checkpoint(machInst); -#if FULL_SYSTEM + case 0x4F: return new M5writefile(machInst); case 0x50: return new M5readfile(machInst); -#endif case 0x51: return new M5break(machInst); case 0x52: return new M5switchcpu(machInst); -#if FULL_SYSTEM case 0x53: return new M5addsymbol(machInst); -#endif case 0x54: return new M5panic(machInst); case 0x5a: return new M5workbegin(machInst); case 0x5b: return new M5workend(machInst); diff --cc src/arch/arm/isa/insts/m5ops.isa index da2e10886,1a154459e..a32bf6dfc --- a/src/arch/arm/isa/insts/m5ops.isa +++ b/src/arch/arm/isa/insts/m5ops.isa @@@ -261,6 -265,24 +261,22 @@@ let { decoder_output += BasicConstructor.subst(m5readfileIop) exec_output += PredOpExecute.subst(m5readfileIop) + m5writefileCode = ''' -#if FULL_SYSTEM + int n = 4; + uint64_t offset = getArgument(xc->tcBase(), n, sizeof(uint64_t), false); + n = 6; + Addr filenameAddr = getArgument(xc->tcBase(), n, sizeof(Addr), false); + R0 = PseudoInst::writefile(xc->tcBase(), R0, join32to64(R3,R2), offset, + filenameAddr); -#endif + ''' + m5writefileIop = InstObjParams("m5writefile", "M5writefile", "PredOp", + { "code": m5writefileCode, + "predicate_test": predicateTest }, + ["IsNonSpeculative"]) + header_output += BasicDeclare.subst(m5writefileIop) + decoder_output += BasicConstructor.subst(m5writefileIop) + exec_output += PredOpExecute.subst(m5writefileIop) + m5breakIop = InstObjParams("m5break", "M5break", "PredOp", { "code": "PseudoInst::debugbreak(xc->tcBase());", "predicate_test": predicateTest }, diff --cc src/arch/arm/tlb.cc index b19ad5265,f4dc47655..0b003e9fb --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@@ -686,6 -703,20 +689,19 @@@ TLB::translateAtomic(RequestPtr req, Th return fault; } + Fault + TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode) + { + bool delay = false; + Fault fault; -#if FULL_SYSTEM - fault = translateFs(req, tc, mode, NULL, delay, false, true); -#else - fault = translateSe(req, tc, mode, NULL, delay, false); -#endif ++ if (FullSystem) ++ fault = translateFs(req, tc, mode, NULL, delay, false, true); ++ else ++ fault = translateSe(req, tc, mode, NULL, delay, false); + assert(!delay); + return fault; + } + Fault TLB::translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode) diff --cc src/arch/arm/tlb.hh index 0bf13fe83,bdfa2fc9f..daf59f01d --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@@ -193,10 -201,14 +199,11 @@@ class TLB : public BaseTL return _attr; } -#if FULL_SYSTEM Fault translateFs(RequestPtr req, ThreadContext *tc, Mode mode, - Translation *translation, bool &delay, bool timing); + Translation *translation, bool &delay, + bool timing, bool functional = false); -#else Fault translateSe(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing); -#endif Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode); Fault translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode); diff --cc src/arch/arm/utility.cc index ac81c7db6,b31dc4324..0527e135f --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@@ -40,12 -40,16 +40,13 @@@ #include "arch/arm/faults.hh" #include "arch/arm/isa_traits.hh" +#include "arch/arm/tlb.hh" #include "arch/arm/utility.hh" +#include "arch/arm/vtophys.hh" + #include "config/use_checker.hh" #include "cpu/thread_context.hh" - -#if FULL_SYSTEM -#include "arch/arm/vtophys.hh" #include "mem/fs_translating_port_proxy.hh" -#endif - -#include "arch/arm/tlb.hh" +#include "sim/full_system.hh" namespace ArmISA { diff --cc src/cpu/BaseCPU.py index 19464acbc,77ba35b19..fda0a3bc8 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@@ -170,16 -183,22 +169,21 @@@ class BaseCPU(MemObject) self.icache_port = ic.cpu_side self.dcache_port = dc.cpu_side self._cached_ports = ['icache.mem_side', 'dcache.mem_side'] - if buildEnv['FULL_SYSTEM']: - if buildEnv['TARGET_ISA'] in ['x86', 'arm']: - if iwc and dwc: - self.itb_walker_cache = iwc - self.dtb_walker_cache = dwc - self.itb.walker.port = iwc.cpu_side - self.dtb.walker.port = dwc.cpu_side - self._cached_ports += ["itb_walker_cache.mem_side", \ - "dtb_walker_cache.mem_side"] - else: - self._cached_ports += ["itb.walker.port", "dtb.walker.port"] - # Checker doesn't need its own tlb caches because it does - # functional accesses only - if buildEnv['USE_CHECKER']: - self._cached_ports += ["checker.itb.walker.port", \ - "checker.dtb.walker.port"] + if buildEnv['TARGET_ISA'] in ['x86', 'arm']: + if iwc and dwc: + self.itb_walker_cache = iwc + self.dtb_walker_cache = dwc + self.itb.walker.port = iwc.cpu_side + self.dtb.walker.port = dwc.cpu_side + self._cached_ports += ["itb_walker_cache.mem_side", \ + "dtb_walker_cache.mem_side"] + else: + self._cached_ports += ["itb.walker.port", "dtb.walker.port"] ++ # Checker doesn't need its own tlb caches because it does ++ # functional accesses only ++ if buildEnv['USE_CHECKER']: ++ self._cached_ports += ["checker.itb.walker.port", \ ++ "checker.dtb.walker.port"] def addTwoLevelCacheHierarchy(self, ic, dc, l2c, iwc = None, dwc = None): self.addPrivateSplitL1Caches(ic, dc, iwc, dwc) diff --cc src/cpu/SConscript index ff731336a,5b276380e..de59dcc24 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@@ -129,12 -126,20 +129,14 @@@ Source('simple_thread.cc' Source('thread_context.cc') Source('thread_state.cc') -if env['FULL_SYSTEM']: - SimObject('IntrControl.py') - - Source('intr_control.cc') - Source('profile.cc') - - if env['TARGET_ISA'] == 'sparc': - SimObject('LegionTrace.py') - Source('legiontrace.cc') +if env['TARGET_ISA'] == 'sparc': + SimObject('LegionTrace.py') + Source('legiontrace.cc') if env['USE_CHECKER']: + SimObject('DummyChecker.py') Source('checker/cpu.cc') + Source('dummy_checker_builder.cc') DebugFlag('Checker') checker_supports = False for i in CheckerSupportedCPUList: diff --cc src/cpu/base.cc index d174995a9,f9ae9ce5d..977769126 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@@ -212,13 -223,16 +217,16 @@@ BaseCPU::BaseCPU(Params *p schedule(event, p->function_trace_start); } } - interrupts->setCPU(this); -#if FULL_SYSTEM + // Check if CPU model has interrupts connected. The CheckerCPU + // cannot take interrupts directly for example. + if (interrupts) + interrupts->setCPU(this); - profileEvent = NULL; - if (params()->profile) - profileEvent = new ProfileEvent(this, params()->profile); -#endif + if (FullSystem) { + profileEvent = NULL; + if (params()->profile) + profileEvent = new ProfileEvent(this, params()->profile); + } tracer = params()->tracer; } @@@ -396,8 -418,38 +406,37 @@@ BaseCPU::takeOverFrom(BaseCPU *oldCPU new_dtb_port->setPeer(peer); peer->setPeer(new_dtb_port); } + + #if USE_CHECKER + Port *old_checker_itb_port, *old_checker_dtb_port; + Port *new_checker_itb_port, *new_checker_dtb_port; + + CheckerCPU *oldChecker = + dynamic_cast(oldTC->getCheckerCpuPtr()); + CheckerCPU *newChecker = + dynamic_cast(newTC->getCheckerCpuPtr()); + old_checker_itb_port = oldChecker->getITBPtr()->getPort(); + old_checker_dtb_port = oldChecker->getDTBPtr()->getPort(); + new_checker_itb_port = newChecker->getITBPtr()->getPort(); + new_checker_dtb_port = newChecker->getDTBPtr()->getPort(); + + // Move over any table walker ports if they exist for checker + if (new_checker_itb_port && !new_checker_itb_port->isConnected()) { + assert(old_checker_itb_port); + Port *peer = old_checker_itb_port->getPeer();; + new_checker_itb_port->setPeer(peer); + peer->setPeer(new_checker_itb_port); + } + if (new_checker_dtb_port && !new_checker_dtb_port->isConnected()) { + assert(old_checker_dtb_port); + Port *peer = old_checker_dtb_port->getPeer();; + new_checker_dtb_port->setPeer(peer); + peer->setPeer(new_checker_dtb_port); + } + #endif + } -#if FULL_SYSTEM interrupts = oldCPU->interrupts; interrupts->setCPU(this); diff --cc src/cpu/base_dyn_inst.hh index 9089d1069,14889a206..2b0e26cd2 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@@ -53,7 -54,9 +54,8 @@@ #include "arch/utility.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" -#include "config/full_system.hh" #include "config/the_isa.hh" + #include "config/use_checker.hh" #include "cpu/o3/comm.hh" #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" diff --cc src/cpu/checker/cpu.cc index ec4496eb4,7c9e4f781..c905c62eb --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@@ -38,10 -49,16 +51,11 @@@ #include "cpu/simple_thread.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" + #include "params/CheckerCPU.hh" + #include "sim/tlb.hh" -#if FULL_SYSTEM -#include "arch/kernel_stats.hh" -#include "arch/vtophys.hh" -#endif // FULL_SYSTEM - using namespace std; - //The CheckerCPU does alpha only - using namespace AlphaISA; + using namespace TheISA; void CheckerCPU::init() @@@ -65,14 -84,18 +81,15 @@@ CheckerCPU::CheckerCPU(Params *p warnOnlyOnLoadError = p->warnOnlyOnLoadError; itb = p->itb; dtb = p->dtb; -#if FULL_SYSTEM systemPtr = NULL; - process = p->process; - thread = new SimpleThread(this, /* thread_num */ 0, process); -#else + workload = p->workload; + // XXX: This is a hack to get this to work some + thread = new SimpleThread(this, /* thread_num */ 0, workload[0], itb, dtb); tc = thread->getTC(); threadContexts.push_back(tc); -#endif - result.integer = 0; + updateOnError = true; } CheckerCPU::~CheckerCPU() @@@ -119,198 -137,215 +129,213 @@@ CheckerCPU::serialize(ostream &os void CheckerCPU::unserialize(Checkpoint *cp, const string §ion) { - /* - BaseCPU::unserialize(cp, section); - UNSERIALIZE_SCALAR(inst); - thread->unserialize(cp, csprintf("%s.xc", section)); - */ } - template Fault - CheckerCPU::read(Addr addr, T &data, unsigned flags) + CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags) { - // need to fill in CPU & thread IDs here - memReq = new Request(); + Fault fault = NoFault; + unsigned blockSize = dcachePort->peerBlockSize(); + int fullSize = size; + Addr secondAddr = roundDown(addr + size - 1, blockSize); + bool checked_flags = false; + bool flags_match = true; + Addr pAddr = 0x0; + + + if (secondAddr > addr) + size = secondAddr - addr; + + // Need to account for multiple accesses like the Atomic and TimingSimple + while (1) { + memReq = new Request(); + memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr()); + + // translate to physical address + fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read); + + if (!checked_flags && fault == NoFault && unverifiedReq) { + flags_match = checkFlags(unverifiedReq, memReq->getVaddr(), + memReq->getPaddr(), memReq->getFlags()); + pAddr = memReq->getPaddr(); + checked_flags = true; + } - memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); + // Now do the access + if (fault == NoFault && + !memReq->getFlags().isSet(Request::NO_ACCESS)) { + PacketPtr pkt = new Packet(memReq, + memReq->isLLSC() ? + MemCmd::LoadLockedReq : MemCmd::ReadReq, + Packet::Broadcast); + + pkt->dataStatic(data); + + if (!(memReq->isUncacheable() || memReq->isMmappedIpr())) { + // Access memory to see if we have the same data + dcachePort->sendFunctional(pkt); + } else { + // Assume the data is correct if it's an uncached access + memcpy(data, unverifiedMemData, size); + } + + delete memReq; + memReq = NULL; + delete pkt; + } - // translate to physical address - dtb->translateAtomic(memReq, tc, false); + if (fault != NoFault) { + if (memReq->isPrefetch()) { + fault = NoFault; + } + delete memReq; + memReq = NULL; + break; + } - PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); + if (memReq != NULL) { + delete memReq; + } - pkt->dataStatic(&data); + //If we don't need to access a second cache line, stop now. + if (secondAddr <= addr) + { + break; + } - if (!(memReq->isUncacheable())) { - // Access memory to see if we have the same data - dcachePort->sendFunctional(pkt); - } else { - // Assume the data is correct if it's an uncached access - memcpy(&data, &unverifiedResult.integer, sizeof(T)); + // Setup for accessing next cache line + data += size; + unverifiedMemData += size; + size = addr + fullSize - secondAddr; + addr = secondAddr; } - delete pkt; + if (!flags_match) { + warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n", + curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), + unverifiedReq->getFlags(), addr, pAddr, flags); + handleError(); + } - return NoFault; + return fault; } - #ifndef DOXYGEN_SHOULD_SKIP_THIS - - template - Fault - CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); - - template - Fault - CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); - - template Fault - CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); - - template - Fault - CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); - - #endif //DOXYGEN_SHOULD_SKIP_THIS - - template<> - Fault - CheckerCPU::read(Addr addr, double &data, unsigned flags) + CheckerCPU::writeMem(uint8_t *data, unsigned size, + Addr addr, unsigned flags, uint64_t *res) { - return read(addr, *(uint64_t*)&data, flags); - } + Fault fault = NoFault; + bool checked_flags = false; + bool flags_match = true; + Addr pAddr = 0x0; - template<> - Fault - CheckerCPU::read(Addr addr, float &data, unsigned flags) - { - return read(addr, *(uint32_t*)&data, flags); - } + unsigned blockSize = dcachePort->peerBlockSize(); + int fullSize = size; - template<> - Fault - CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) - { - return read(addr, (uint32_t&)data, flags); - } + Addr secondAddr = roundDown(addr + size - 1, blockSize); - template - Fault - CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) - { - // need to fill in CPU & thread IDs here - memReq = new Request(); - - memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); - - // translate to physical address - dtb->translateAtomic(memReq, tc, true); - - // Can compare the write data and result only if it's cacheable, - // not a store conditional, or is a store conditional that - // succeeded. - // @todo: Verify that actual memory matches up with these values. - // Right now it only verifies that the instruction data is the - // same as what was in the request that got sent to memory; there - // is no verification that it is the same as what is in memory. - // This is because the LSQ would have to be snooped in the CPU to - // verify this data. - if (unverifiedReq && - !(unverifiedReq->isUncacheable()) && - (!(unverifiedReq->isLLSC()) || - ((unverifiedReq->isLLSC()) && - unverifiedReq->getExtraData() == 1))) { - T inst_data; - /* - // This code would work if the LSQ allowed for snooping. - PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); - pkt.dataStatic(&inst_data); + if (secondAddr > addr) + size = secondAddr - addr; - dcachePort->sendFunctional(pkt); + // Need to account for a multiple access like Atomic and Timing CPUs + while (1) { + memReq = new Request(); + memReq->setVirt(0, addr, size, flags, thread->pcState().instAddr()); - delete pkt; - */ - memcpy(&inst_data, unverifiedMemData, sizeof(T)); + // translate to physical address + fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write); - if (data != inst_data) { - warn("%lli: Store value does not match value in memory! " - "Instruction: %#x, memory: %#x", - curTick(), inst_data, data); - handleError(); + if (!checked_flags && fault == NoFault && unverifiedReq) { + flags_match = checkFlags(unverifiedReq, memReq->getVaddr(), + memReq->getPaddr(), memReq->getFlags()); + pAddr = memReq->getPaddr(); + checked_flags = true; } - } - - // Assume the result was the same as the one passed in. This checker - // doesn't check if the SC should succeed or fail, it just checks the - // value. - if (res && unverifiedReq->scResultValid()) - *res = unverifiedReq->getExtraData(); - - return NoFault; - } - - - #ifndef DOXYGEN_SHOULD_SKIP_THIS - template - Fault - CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); - - template - Fault - CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); - - template - Fault - CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); - - template - Fault - CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); - - #endif //DOXYGEN_SHOULD_SKIP_THIS - template<> - Fault - CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) - { - return write(*(uint64_t*)&data, addr, flags, res); - } - - template<> - Fault - CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) - { - return write(*(uint32_t*)&data, addr, flags, res); - } + /* + * We don't actually check memory for the store because there + * is no guarantee it has left the lsq yet, and therefore we + * can't verify the memory on stores without lsq snooping + * enabled. This is left as future work for the Checker: LSQ snooping + * and memory validation after stores have committed. + */ + + delete memReq; + + //If we don't need to access a second cache line, stop now. + if (fault != NoFault || secondAddr <= addr) + { + if (fault != NoFault && memReq->isPrefetch()) { + fault = NoFault; + } + break; + } - template<> - Fault - CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) - { - return write((uint32_t)data, addr, flags, res); + //Update size and access address + size = addr + fullSize - secondAddr; + //And access the right address. + addr = secondAddr; + } + + if (!flags_match) { + warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n", + curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), + unverifiedReq->getFlags(), addr, pAddr, flags); + handleError(); + } + + // Assume the result was the same as the one passed in. This checker + // doesn't check if the SC should succeed or fail, it just checks the + // value. + if (unverifiedReq && res && unverifiedReq->extraDataValid()) + *res = unverifiedReq->getExtraData(); + + // Entire purpose here is to make sure we are getting the + // same data to send to the mem system as the CPU did. + // Cannot check this is actually what went to memory because + // there stores can be in ld/st queue or coherent operations + // overwriting values. + bool extraData; + if (unverifiedReq) { + extraData = unverifiedReq->extraDataValid() ? + unverifiedReq->getExtraData() : 1; + } + + if (unverifiedReq && unverifiedMemData && + memcmp(data, unverifiedMemData, fullSize) && extraData) { + warn("%lli: Store value does not match value sent to memory!\ + data: %#x inst_data: %#x", curTick(), data, + unverifiedMemData); + handleError(); + } + + return fault; } - -#if FULL_SYSTEM Addr CheckerCPU::dbg_vtophys(Addr addr) { return vtophys(tc, addr); } -#endif // FULL_SYSTEM + /** + * Checks if the flags set by the Checker and Checkee match. + */ bool - CheckerCPU::checkFlags(Request *req) + CheckerCPU::checkFlags(Request *unverified_req, Addr vAddr, + Addr pAddr, int flags) { - // Remove any dynamic flags that don't have to do with the request itself. - unsigned flags = unverifiedReq->getFlags(); - unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH; - flags = flags & (mask); - if (flags == req->getFlags()) { + Addr unverifiedVAddr = unverified_req->getVaddr(); + Addr unverifiedPAddr = unverified_req->getPaddr(); + int unverifiedFlags = unverified_req->getFlags(); + + if (unverifiedVAddr != vAddr || + unverifiedPAddr != pAddr || + unverifiedFlags != flags) { return false; - } else { - return true; } + + return true; } void diff --cc src/cpu/checker/cpu.hh index a3e95137d,1419051a6..6f5125625 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@@ -35,8 -47,10 +47,9 @@@ #include #include + #include "arch/predecoder.hh" #include "arch/types.hh" #include "base/statistics.hh" -#include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/pc_event.hh" @@@ -49,16 -66,19 +64,10 @@@ namespace TheIS { class TLB; } -class Processor; -class PhysicalMemory; -#else - -class Process; - -#endif // FULL_SYSTEM template class BaseDynInst; - class CheckerCPUParams; - class Checkpoint; - class MemInterface; - class PhysicalMemory; - class Process; - class Processor; class ThreadContext; -class MemInterface; -class Checkpoint; class Request; /** @@@ -265,8 -328,19 +315,17 @@@ class CheckerCPU : public BaseCP this->dtb->demapPage(vaddr, asn); } + Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); + Fault writeMem(uint8_t *data, unsigned size, + Addr addr, unsigned flags, uint64_t *res); + + void setStCondFailures(unsigned sc_failures) + {} + ///////////////////////////////////////////////////// + -#if FULL_SYSTEM Fault hwrei() { return thread->hwrei(); } bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } + void wakeup() { } -#else // Assume that the normal CPU's call to syscall was successful. // The checker's state would have already been updated by the syscall. void syscall(uint64_t callnum) { } diff --cc src/cpu/checker/cpu_impl.hh index 7d8cc8a19,8c8789cb6..7a99feb06 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@@ -31,25 -44,83 +44,81 @@@ #include #include +#include "arch/vtophys.hh" #include "base/refcnt.hh" #include "config/the_isa.hh" - #include "cpu/checker/cpu.hh" #include "cpu/base_dyn_inst.hh" + #include "cpu/exetrace.hh" #include "cpu/simple_thread.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" + #include "cpu/checker/cpu.hh" + #include "debug/Checker.hh" +#include "sim/full_system.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" -#if FULL_SYSTEM -#include "arch/vtophys.hh" -#endif // FULL_SYSTEM - using namespace std; - //The CheckerCPU does alpha only - using namespace AlphaISA; + using namespace TheISA; + + template + void + Checker::advancePC(Fault fault) + { + if (fault != NoFault) { + curMacroStaticInst = StaticInst::nullStaticInstPtr; + fault->invoke(tc, curStaticInst); + predecoder.reset(); + } else { + if (curStaticInst) { + if (curStaticInst->isLastMicroop()) + curMacroStaticInst = StaticInst::nullStaticInstPtr; + TheISA::PCState pcState = thread->pcState(); + TheISA::advancePC(pcState, curStaticInst); + thread->pcState(pcState); + DPRINTF(Checker, "Advancing PC to %s.\n", thread->pcState()); + } + } + } + ////////////////////////////////////////////////// + + template + void + Checker::handlePendingInt() + { + DPRINTF(Checker, "IRQ detected at PC: %s with %d insts in buffer\n", + thread->pcState(), instList.size()); + DynInstPtr boundaryInst = NULL; + if (!instList.empty()) { + // Set the instructions as completed and verify as much as possible. + DynInstPtr inst; + typename std::list::iterator itr; + + for (itr = instList.begin(); itr != instList.end(); itr++) { + (*itr)->setCompleted(); + } + + inst = instList.front(); + boundaryInst = instList.back(); + verify(inst); // verify the instructions + inst = NULL; + } + if ((!boundaryInst && curMacroStaticInst && + curStaticInst->isDelayedCommit() && + !curStaticInst->isLastMicroop()) || + (boundaryInst && boundaryInst->isDelayedCommit() && + !boundaryInst->isLastMicroop())) { + panic("%lli: Trying to take an interrupt in middle of " + "a non-interuptable instruction!", curTick()); + } + boundaryInst = NULL; + predecoder.reset(); + curMacroStaticInst = StaticInst::nullStaticInstPtr; + } - template + template void - Checker::verify(DynInstPtr &completed_inst) + Checker::verify(DynInstPtr &completed_inst) { DynInstPtr inst; @@@ -228,42 -399,36 +397,34 @@@ } } + // Take any faults here if (fault != NoFault) { -#if FULL_SYSTEM fault->invoke(tc, curStaticInst); willChangePC = true; - newPC = thread->readPC(); - DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); + newPCState = thread->pcState(); + DPRINTF(Checker, "Fault, PC is now %s\n", newPCState); + curMacroStaticInst = StaticInst::nullStaticInstPtr; -#endif } else { - #if THE_ISA != MIPS_ISA - // go to the next instruction - thread->setPC(thread->readNextPC()); - thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); - #else - // go to the next instruction - thread->setPC(thread->readNextPC()); - thread->setNextPC(thread->readNextNPC()); - thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); - #endif - + advancePC(fault); } -#if FULL_SYSTEM - // @todo: Determine if these should happen only if the - // instruction hasn't faulted. In the SimpleCPU case this may - // not be true, but in the O3 or Ozone case this may be true. - Addr oldpc; - int count = 0; - do { - oldpc = thread->instAddr(); - system->pcEventQueue.service(tc); - count++; - } while (oldpc != thread->instAddr()); - if (count > 1) { - willChangePC = true; - newPCState = thread->pcState(); - DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState); + if (FullSystem) { + // @todo: Determine if these should happen only if the + // instruction hasn't faulted. In the SimpleCPU case this may + // not be true, but in the O3 or Ozone case this may be true. + Addr oldpc; + int count = 0; + do { - oldpc = thread->readPC(); ++ oldpc = thread->instAddr(); + system->pcEventQueue.service(tc); + count++; - } while (oldpc != thread->readPC()); ++ } while (oldpc != thread->instAddr()); + if (count > 1) { + willChangePC = true; - newPC = thread->readPC(); - DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); ++ newPCState = thread->pcState(); ++ DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState); + } } -#endif // @todo: Optionally can check all registers. (Or just those // that have been modified). diff --cc src/cpu/checker/thread_context.hh index 178ded80e,d66854b23..d21de9f53 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@@ -89,8 -112,13 +112,12 @@@ class CheckerThreadContext : public Thr TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); } + BaseCPU *getCheckerCpuPtr() { return checkerTC->getCpuPtr(); } + + Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); } + System *getSystemPtr() { return actualTC->getSystemPtr(); } -#if FULL_SYSTEM PhysicalMemory *getPhysMemPtr() { return actualTC->getPhysMemPtr(); } TheISA::Kernel::Statistics *getKernelStats() @@@ -103,8 -129,24 +130,21 @@@ FSTranslatingPortProxy* getVirtProxy() { return actualTC->getVirtProxy(); } + //XXX: How does this work now? + void initMemProxies(ThreadContext *tc) + { actualTC->initMemProxies(tc); } + + void connectMemPorts(ThreadContext *tc) + { + actualTC->connectMemPorts(tc); + } -#else - SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); } + - Process *getProcessPtr() { return actualTC->getProcessPtr(); } + SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); } + /** Executes a syscall in SE mode. */ + void syscall(int64_t callnum) + { return actualTC->syscall(callnum); } -#endif + Status status() const { return actualTC->status(); } void setStatus(Status new_status) @@@ -118,12 -160,14 +158,12 @@@ void activate(int delay = 1) { actualTC->activate(delay); } /// Set the status to Suspended. - void suspend() { actualTC->suspend(); } + void suspend(int delay) { actualTC->suspend(delay); } /// Set the status to Halted. - void halt() { actualTC->halt(); } + void halt(int delay) { actualTC->halt(delay); } -#if FULL_SYSTEM void dumpFuncProfile() { actualTC->dumpFuncProfile(); } -#endif void takeOverFrom(ThreadContext *oldContext) { @@@ -144,9 -193,8 +188,7 @@@ void profileClear() { return actualTC->profileClear(); } void profileSample() { return actualTC->profileSample(); } -#endif - int threadId() { return actualTC->threadId(); } - // @todo: Do I need this? void copyArchRegs(ThreadContext *tc) { diff --cc src/cpu/dummy_checker_builder.cc index 000000000,28f060931..0c83dabd0 mode 000000,100644..100644 --- a/src/cpu/dummy_checker_builder.cc +++ b/src/cpu/dummy_checker_builder.cc @@@ -1,0 -1,100 +1,97 @@@ + /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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. + * + * Authors: Geoffrey Blake + */ + + #include + + #include "cpu/checker/cpu.hh" + #include "cpu/inst_seq.hh" + #include "params/DummyChecker.hh" + #include "sim/process.hh" + #include "sim/sim_object.hh" + + class MemObject; + + /** + * Specific non-templated derived class used for SimObject configuration. + */ + class DummyChecker : public CheckerCPU + { + public: + DummyChecker(Params *p) + : CheckerCPU(p) + { } + }; + + //////////////////////////////////////////////////////////////////////// + // + // DummyChecker Simulation Object + // + DummyChecker * + DummyCheckerParams::create() + { + DummyChecker::Params *params = new DummyChecker::Params(); + params->name = name; + params->numThreads = numThreads; + params->max_insts_any_thread = 0; + params->max_insts_all_threads = 0; + params->max_loads_any_thread = 0; + params->max_loads_all_threads = 0; + params->clock = clock; + // Hack to touch all parameters. Consider not deriving Checker + // from BaseCPU..it's not really a CPU in the end. + Counter temp; + temp = max_insts_any_thread; + temp = max_insts_all_threads; + temp = max_loads_any_thread; + temp = max_loads_all_threads; + Tick temp2 = progress_interval; + params->progress_interval = 0; + temp2++; + + params->itb = itb; + params->dtb = dtb; + params->system = system; + params->cpu_id = cpu_id; -#if FULL_SYSTEM + params->profile = profile; + params->interrupts = NULL; -#else + params->workload = workload; -#endif + + DummyChecker *cpu = new DummyChecker(params); + return cpu; + } diff --cc src/cpu/o3/O3CPU.py index c3e561cd9,edce7d8c7..acc7a9056 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@@ -40,11 -40,21 +40,15 @@@ class DerivO3CPU(BaseCPU) activity = Param.Unsigned(0, "Initial count") if buildEnv['USE_CHECKER']: - checker = Param.BaseCPU(O3Checker(workload=Parent.workload, - if not buildEnv['FULL_SYSTEM']: - # FIXME: Shouldn't need to derefernce Parent.workload - # Somewhere in the param parsing code - # src/python/m5/params.py is and error that - # has trouble converting the workload parameter properly. - checker = Param.BaseCPU(O3Checker(workload=Parent.workload[0], - exitOnError=False, - updateOnError=True, - warnOnlyOnLoadError=True), - "checker") - else: - checker = Param.BaseCPU(O3Checker(exitOnError=False, - updateOnError=True, - warnOnlyOnLoadError=True), - "checker") ++ # FIXME: Shouldn't need to derefernce Parent.workload ++ # Somewhere in the param parsing code ++ # src/python/m5/params.py is and error that ++ # has trouble converting the workload parameter properly. ++ checker = Param.BaseCPU(O3Checker(workload=Parent.workload[0], + exitOnError=False, + updateOnError=True, - warnOnlyOnLoadError=False), - "checker") ++ warnOnlyOnLoadError=True), ++ "checker") checker.itb = Parent.itb checker.dtb = Parent.dtb diff --cc src/cpu/o3/checker_builder.cc index b34613f68,73e8b5162..72b50d104 --- a/src/cpu/o3/checker_builder.cc +++ b/src/cpu/o3/checker_builder.cc @@@ -90,8 -100,12 +100,9 @@@ O3CheckerParams::create( params->dtb = dtb; params->system = system; params->cpu_id = cpu_id; -#if FULL_SYSTEM params->profile = profile; - params->process = workload; + params->interrupts = NULL; -#else + params->workload = workload; -#endif O3Checker *cpu = new O3Checker(params); return cpu; diff --cc src/cpu/o3/commit_impl.hh index b6a4c0387,cb2f9a634..edf7e861b --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@@ -768,16 -779,17 +774,16 @@@ template ::commit() { - -#if FULL_SYSTEM - // Check for any interrupt that we've already squashed for and - // start processing it. - if (interrupt != NoFault) - handleInterrupt(); - - // Check if we have a interrupt and get read to handle it - if (cpu->checkInterrupts(cpu->tcBase(0))) - propagateInterrupt(); -#endif // FULL_SYSTEM + if (FullSystem) { - // Check for any interrupt that we've already squashed for and start - // processing it. ++ // Check for any interrupt that we've already squashed for and ++ // start processing it. + if (interrupt != NoFault) + handleInterrupt(); + + // Check if we have a interrupt and get read to handle it + if (cpu->checkInterrupts(cpu->tcBase(0))) + propagateInterrupt(); + } //////////////////////////////////// // Check for any possible squashes, handle them first diff --cc src/cpu/o3/cpu.cc index ef08c96f4,cede7ae18..d16270943 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@@ -63,8 -60,15 +63,9 @@@ #include "sim/stat_control.hh" #include "sim/system.hh" -#if FULL_SYSTEM -#include "cpu/quiesce_event.hh" -#else -#include "sim/process.hh" -#endif - #if USE_CHECKER #include "cpu/checker/cpu.hh" + #include "cpu/checker/thread_context.hh" #endif #if THE_ISA == ALPHA_ISA @@@ -265,9 -269,11 +266,9 @@@ FullO3CPU::FullO3CPU(DerivO3CPUPa #if USE_CHECKER if (params->checker) { BaseCPU *temp_checker = params->checker; - checker = dynamic_cast *>(temp_checker); + checker = dynamic_cast *>(temp_checker); checker->setIcachePort(&icachePort); -#if FULL_SYSTEM checker->setSystem(params->system); -#endif } else { checker = NULL; } diff --cc src/cpu/o3/decode_impl.hh index 985e92826,7fa25106a..60bca1041 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@@ -36,9 -37,10 +36,11 @@@ #include "debug/Activity.hh" #include "debug/Decode.hh" #include "params/DerivO3CPU.hh" +#include "sim/full_system.hh" - using namespace std; + // clang complains about std::set being overloaded with Packet::set if + // we open up the entire namespace std + using std::list; template DefaultDecode::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params) diff --cc src/cpu/o3/dyn_inst_impl.hh index 76a456ee3,8a01b2575..ed1e374e8 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@@ -41,8 -41,8 +41,9 @@@ */ #include "base/cp_annotate.hh" + #include "config/use_checker.hh" #include "cpu/o3/dyn_inst.hh" +#include "sim/full_system.hh" template BaseO3DynInst::BaseO3DynInst(StaticInstPtr staticInst, diff --cc src/cpu/o3/fetch_impl.hh index 1b82f8a4c,463509cf1..553198980 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@@ -43,11 -43,12 +43,14 @@@ #include #include + #include + #include + #include #include "arch/isa_traits.hh" +#include "arch/tlb.hh" #include "arch/utility.hh" +#include "arch/vtophys.hh" #include "base/types.hh" #include "config/the_isa.hh" #include "config/use_checker.hh" @@@ -63,9 -63,17 +65,13 @@@ #include "sim/byteswap.hh" #include "sim/core.hh" #include "sim/eventq.hh" - -#if FULL_SYSTEM -#include "arch/tlb.hh" -#include "arch/vtophys.hh" +#include "sim/full_system.hh" #include "sim/system.hh" -#endif // FULL_SYSTEM + #if USE_CHECKER + #include "cpu/checker/cpu.hh" + #endif // USE_CHECKER + using namespace std; template diff --cc src/cpu/o3/thread_context_impl.hh index 5ba454458,5a412c161..2ea39f3eb --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@@ -41,9 -41,9 +41,10 @@@ * Korey Sewell */ +#include "arch/kernel_stats.hh" #include "arch/registers.hh" #include "config/the_isa.hh" + #include "config/use_checker.hh" #include "cpu/o3/thread_context.hh" #include "cpu/quiesce_event.hh" #include "debug/O3CPU.hh" diff --cc src/cpu/simple/base.cc index 610cc6b89,e56dc0fbb..97ce3264a --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@@ -79,6 -74,20 +80,11 @@@ #include "sim/stats.hh" #include "sim/system.hh" -#if FULL_SYSTEM -#include "arch/kernel_stats.hh" -#include "arch/stacktrace.hh" -#include "arch/tlb.hh" -#include "arch/vtophys.hh" -#else // !FULL_SYSTEM -#include "mem/mem_object.hh" -#endif // FULL_SYSTEM - + #if USE_CHECKER + #include "cpu/checker/cpu.hh" + #include "cpu/checker/thread_context.hh" + #endif + using namespace std; using namespace TheISA; @@@ -95,6 -105,21 +101,19 @@@ BaseSimpleCPU::BaseSimpleCPU(BaseSimple tc = thread->getTC(); + #if USE_CHECKER + if (p->checker) { + BaseCPU *temp_checker = p->checker; + checker = dynamic_cast(temp_checker); -#if FULL_SYSTEM + checker->setSystem(p->system); -#endif + // Manipulate thread context + ThreadContext *cpu_tc = tc; + tc = new CheckerThreadContext(cpu_tc, this->checker); + } else { + checker = NULL; + } + #endif + numInst = 0; startNumInst = 0; numLoad = 0; diff --cc src/cpu/simple/base.hh index 0e5526040,3535539d0..55dec5d53 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@@ -35,7 -47,9 +47,8 @@@ #include "arch/predecoder.hh" #include "base/statistics.hh" -#include "config/full_system.hh" #include "config/the_isa.hh" + #include "config/use_checker.hh" #include "cpu/base.hh" #include "cpu/decode.hh" #include "cpu/pc_event.hh" @@@ -45,15 -59,27 +58,19 @@@ #include "mem/port.hh" #include "mem/request.hh" #include "sim/eventq.hh" +#include "sim/full_system.hh" #include "sim/system.hh" + #if USE_CHECKER + #include "cpu/checker/cpu.hh" + #endif + // forward declarations -#if FULL_SYSTEM -class Processor; -namespace TheISA -{ - class ITB; - class DTB; -} +class Checkpoint; class MemObject; - -#else - class Process; - -#endif // FULL_SYSTEM +class Processor; +class ThreadContext; namespace TheISA { diff --cc src/cpu/simple_thread.cc index a12ab8e8a,8e7127269..e193b1273 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@@ -41,39 -48,27 +41,35 @@@ #include "base/cprintf.hh" #include "base/output.hh" #include "base/trace.hh" +#include "config/the_isa.hh" +#include "cpu/base.hh" #include "cpu/profile.hh" #include "cpu/quiesce_event.hh" +#include "cpu/simple_thread.hh" +#include "cpu/thread_context.hh" - #include "params/BaseCPU.hh" #include "mem/fs_translating_port_proxy.hh" -#include "sim/serialize.hh" -#include "sim/sim_exit.hh" -#else #include "mem/se_translating_port_proxy.hh" ++#include "params/BaseCPU.hh" +#include "sim/full_system.hh" #include "sim/process.hh" +#include "sim/serialize.hh" +#include "sim/sim_exit.hh" - #include "sim/process.hh" #include "sim/system.hh" -#endif using namespace std; // constructor -#if FULL_SYSTEM +SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, + TheISA::TLB *_itb, TheISA::TLB *_dtb) - : ThreadState(_cpu, _thread_num, _process), - cpu(_cpu), itb(_itb), dtb(_dtb) ++ : ThreadState(_cpu, _thread_num, _process), itb(_itb), dtb(_dtb) +{ + clearArchRegs(); + tc = new ProxyThreadContext(this); +} SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, TheISA::TLB *_itb, TheISA::TLB *_dtb, bool use_kernel_stats) - : ThreadState(_cpu, _thread_num, NULL), - cpu(_cpu), system(_sys), itb(_itb), dtb(_dtb) - : ThreadState(_cpu, _thread_num), - system(_sys), itb(_itb), dtb(_dtb) -- ++ : ThreadState(_cpu, _thread_num, NULL), system(_sys), itb(_itb), dtb(_dtb) { tc = new ProxyThreadContext(this); @@@ -199,15 -212,18 +195,16 @@@ SimpleThread::unserialize(Checkpoint *c // // Now must unserialize all the ISA dependent state // - isa.unserialize(cpu, cp, section); + isa.unserialize(baseCpu, cp, section); } -#if FULL_SYSTEM void SimpleThread::dumpFuncProfile() { - std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); + std::ostream *os = simout.create(csprintf("profile.%s.dat", + baseCpu->name())); profile->dump(tc, *os); } -#endif void SimpleThread::activate(int delay) @@@ -236,8 -252,17 +233,8 @@@ SimpleThread::suspend( lastActivate = curTick(); lastSuspend = curTick(); -/* -#if FULL_SYSTEM - // Don't change the status from active if there are pending interrupts - if (cpu->checkInterrupts()) { - assert(status() == ThreadContext::Active); - return; - } -#endif -*/ _status = ThreadContext::Suspended; - cpu->suspendContext(_threadId); + baseCpu->suspendContext(_threadId); } diff --cc src/cpu/simple_thread.hh index 97964c0e8,46ed92ce8..39cb96c3a --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@@ -38,7 -50,9 +50,8 @@@ #include "arch/tlb.hh" #include "arch/types.hh" #include "base/types.hh" -#include "config/full_system.hh" #include "config/the_isa.hh" + #include "config/use_checker.hh" #include "cpu/decode.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" diff --cc src/cpu/thread_context.hh index 261ace7cf,946c35249..2f2e5b02b --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@@ -37,7 -49,9 +49,8 @@@ #include "arch/registers.hh" #include "arch/types.hh" #include "base/types.hh" -#include "config/full_system.hh" #include "config/the_isa.hh" + #include "config/use_checker.hh" // @todo: Figure out a more architecture independent way to obtain the ITB and // DTB pointers. diff --cc src/cpu/thread_state.hh index 30bb64ed7,f14daaeb8..3622ed37f --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@@ -62,9 -67,13 +62,9 @@@ class FSTranslatingPort struct ThreadState { typedef ThreadContext::Status Status; -#if FULL_SYSTEM - ThreadState(BaseCPU *cpu, ThreadID _tid); -#else ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process); -#endif - ~ThreadState(); + virtual ~ThreadState(); void serialize(std::ostream &os); diff --cc src/sim/pseudo_inst.cc index b72fdca4a,4e6c46f8e..8a7f0c469 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@@ -48,9 -48,10 +48,10 @@@ #include #include +#include "arch/kernel_stats.hh" #include "arch/vtophys.hh" #include "base/debug.hh" + #include "base/output.hh" -#include "config/full_system.hh" #include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/quiesce_event.hh" @@@ -387,6 -359,50 +388,48 @@@ readfile(ThreadContext *tc, Addr vaddr return result; } + uint64_t + writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset, + Addr filename_addr) + { + ostream *os; + + // copy out target filename + char fn[100]; + std::string filename; + CopyStringOut(tc, fn, filename_addr, 100); + filename = std::string(fn); + + if (offset == 0) { + // create a new file (truncate) + os = simout.create(filename, true); + } else { + // do not truncate file if offset is non-zero + // (ios::in flag is required as well to keep the existing data + // intact, otherwise existing data will be zeroed out.) + os = simout.openFile(simout.directory() + filename, + ios::in | ios::out | ios::binary); + } + if (!os) + panic("could not open file %s\n", filename); + + // seek to offset + os->seekp(offset); + + // copy out data and write to file + char *buf = new char[len]; + CopyOut(tc, buf, vaddr, len); + os->write(buf, len); + if (os->fail() || os->bad()) + panic("Error while doing writefile!\n"); + + simout.close(os); + + delete [] buf; + + return len; + } + -#endif - void debugbreak(ThreadContext *tc) {