diff options
author | Kevin Lim <ktlim@umich.edu> | 2006-05-23 17:04:25 -0400 |
---|---|---|
committer | Kevin Lim <ktlim@umich.edu> | 2006-05-23 17:04:25 -0400 |
commit | b414c9e736543acca639c50582c7df7abf59c11b (patch) | |
tree | 8eaa0fa7061af351955c59f0e2a525f3527f2ee7 | |
parent | eeeee7c58f26fac9fe9b8606e26ef8e99a28e399 (diff) | |
parent | 358cf1b11765024309fe986262bb3a3d16c8a720 (diff) | |
download | gem5-b414c9e736543acca639c50582c7df7abf59c11b.tar.xz |
Merge ktlim@zizzer:/bk/m5
into zamp.eecs.umich.edu:/z/ktlim2/clean/m5-o3
--HG--
extra : convert_revision : 0a6140f3f5e7c454981c5aa2b221224f076e50eb
31 files changed, 553 insertions, 784 deletions
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index 019e83dd4..ad3a9ec4c 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -146,7 +146,7 @@ CPUExecContext::hwrei() setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR)); if (!misspeculating()) { - cpu->kernelStats->hwrei(); + kernelStats->hwrei(); cpu->checkInterrupts = true; } @@ -336,7 +336,8 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc) // write entire quad w/ no side-effect old = ipr[idx]; ipr[idx] = val; - xc->getCpuPtr()->kernelStats->context(old, val, xc); + if (xc->getKernelStats()) + xc->getKernelStats()->context(old, val, xc); break; case AlphaISA::IPR_DTB_PTE: @@ -363,14 +364,19 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc) // only write least significant five bits - interrupt level ipr[idx] = val & 0x1f; - xc->getCpuPtr()->kernelStats->swpipl(ipr[idx]); + if (xc->getKernelStats()) + xc->getKernelStats()->swpipl(ipr[idx]); break; case AlphaISA::IPR_DTB_CM: - if (val & 0x18) - xc->getCpuPtr()->kernelStats->mode(Kernel::user, xc); - else - xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc); + if (val & 0x18) { + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::user, xc); + else { + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::kernel, xc); + } + } case AlphaISA::IPR_ICM: // only write two mode bits - processor mode @@ -556,7 +562,7 @@ AlphaISA::MiscRegFile::copyIprs(ExecContext *xc) bool CPUExecContext::simPalCheck(int palFunc) { - cpu->kernelStats->callpal(palFunc, proxy); + kernelStats->callpal(palFunc, proxy); switch (palFunc) { case PAL::halt: diff --git a/cpu/base.cc b/cpu/base.cc index 74b679d5d..de03b9eab 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -45,10 +45,6 @@ #include "base/trace.hh" -#if FULL_SYSTEM -#include "kern/kernel_stats.hh" -#endif - using namespace std; vector<BaseCPU *> BaseCPU::cpuList; @@ -153,8 +149,6 @@ BaseCPU::BaseCPU(Params *p) profileEvent = NULL; if (params->profile) profileEvent = new ProfileEvent(this, params->profile); - - kernelStats = new Kernel::Statistics(system); #endif } @@ -175,10 +169,6 @@ BaseCPU::enableFunctionTrace() BaseCPU::~BaseCPU() { -#if FULL_SYSTEM - if (kernelStats) - delete kernelStats; -#endif } void @@ -219,8 +209,6 @@ BaseCPU::regStats() execContexts[0]->regStats(name()); #if FULL_SYSTEM - if (kernelStats) - kernelStats->regStats(name() + ".kern"); #endif } @@ -348,12 +336,6 @@ BaseCPU::serialize(std::ostream &os) { SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); SERIALIZE_SCALAR(intstatus); - -#if FULL_SYSTEM - if (kernelStats) - kernelStats->serialize(os); -#endif - } void @@ -361,11 +343,6 @@ BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); UNSERIALIZE_SCALAR(intstatus); - -#if FULL_SYSTEM - if (kernelStats) - kernelStats->unserialize(cp, section); -#endif } #endif // FULL_SYSTEM diff --git a/cpu/base.hh b/cpu/base.hh index 20166d7ee..dd776859d 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -38,14 +38,10 @@ #include "sim/sim_object.hh" #include "arch/isa_traits.hh" -#if FULL_SYSTEM -class System; -namespace Kernel { class Statistics; } -#endif - class BranchPred; class CheckerCPU; class ExecContext; +class System; class BaseCPU : public SimObject { @@ -237,10 +233,6 @@ class BaseCPU : public SimObject public: // Number of CPU cycles simulated Stats::Scalar<> numCycles; - -#if FULL_SYSTEM - Kernel::Statistics *kernelStats; -#endif }; #endif // __CPU_BASE_HH__ diff --git a/cpu/base_dyn_inst.hh b/cpu/base_dyn_inst.hh index 9403faec3..388ea4a8d 100644 --- a/cpu/base_dyn_inst.hh +++ b/cpu/base_dyn_inst.hh @@ -450,13 +450,10 @@ class BaseDynInst : public FastAlloc, public RefCounted instResult.integer = val; } - //Push to .cc file. /** Records that one of the source registers is ready. */ void markSrcRegReady(); - /** Marks a specific register as ready. - * @todo: Move this to .cc file. - */ + /** Marks a specific register as ready. */ void markSrcRegReady(RegIndex src_idx); /** Returns if a source register is ready. */ diff --git a/cpu/checker/cpu.cc b/cpu/checker/cpu.cc index f76f1e063..08ab5d5c8 100644 --- a/cpu/checker/cpu.cc +++ b/cpu/checker/cpu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,41 +26,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -//#include <cmath> -#include <cstdio> -//#include <cstdlib> -#include <iostream> -#include <iomanip> #include <list> -//#include <sstream> #include <string> -//#include "base/cprintf.hh" -//#include "base/inifile.hh" -//#include "base/loader/symtab.hh" -#include "base/misc.hh" -//#include "base/pollevent.hh" -//#include "base/range.hh" #include "base/refcnt.hh" -//#include "base/stats/events.hh" #include "cpu/base.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/checker/cpu.hh" #include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" -//#include "cpu/exetrace.hh" -//#include "cpu/profile.hh" -#include "cpu/sampler/sampler.hh" -//#include "cpu/smt.hh" #include "cpu/static_inst.hh" -//#include "kern/kernel_stats.hh" -#include "mem/base_mem.hh" -#include "mem/mem_interface.hh" #include "sim/byteswap.hh" -#include "sim/builder.hh" -//#include "sim/debug.hh" -//#include "sim/host.hh" -//#include "sim/sim_events.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" @@ -72,15 +48,8 @@ #include "cpu/ozone/simple_impl.hh" #if FULL_SYSTEM -#include "base/remote_gdb.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" #include "sim/system.hh" -#include "arch/tlb.hh" -#include "arch/stacktrace.hh" #include "arch/vtophys.hh" -#else // !FULL_SYSTEM -#include "mem/functional/functional.hh" #endif // FULL_SYSTEM using namespace std; @@ -90,17 +59,6 @@ using namespace AlphaISA; void CheckerCPU::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 -*/ } CheckerCPU::CheckerCPU(Params *p) @@ -151,6 +109,8 @@ CheckerCPU::setMemory(FunctionalMemory *mem) xcProxy = cpuXC->getProxy(); execContexts.push_back(xcProxy); memReq->xc = xcProxy; + delete cpuXC->kernelStats; + cpuXC->kernelStats = NULL; } #endif } @@ -168,6 +128,8 @@ CheckerCPU::setSystem(System *system) xcProxy = cpuXC->getProxy(); execContexts.push_back(xcProxy); memReq->xc = xcProxy; + delete cpuXC->kernelStats; + cpuXC->kernelStats = NULL; } } #endif @@ -197,82 +159,15 @@ CheckerCPU::unserialize(Checkpoint *cp, const string §ion) Fault CheckerCPU::copySrcTranslate(Addr src) { - static bool no_warn = true; - int blk_size = 64; - // Only support block sizes of 64 atm. - assert(blk_size == 64); - int offset = src & (blk_size - 1); - - // Make sure block doesn't span page - if (no_warn && - (src & PageMask) != ((src + blk_size) & PageMask) && - (src >> 40) != 0xfffffc) { - warn("Copied block source spans pages %x.", src); - no_warn = false; - } - - memReq->reset(src & ~(blk_size - 1), blk_size); - - // translate to physical address - Fault fault = cpuXC->translateDataReadReq(memReq); - - if (fault == NoFault) { - cpuXC->copySrcAddr = src; - cpuXC->copySrcPhysAddr = memReq->paddr + offset; - } else { - assert(!fault->isAlignmentFault()); - - cpuXC->copySrcAddr = 0; - cpuXC->copySrcPhysAddr = 0; - } - return fault; + panic("Unimplemented!"); } Fault CheckerCPU::copy(Addr dest) { - static bool no_warn = true; - int blk_size = 64; - // Only support block sizes of 64 atm. - assert(blk_size == 64); - uint8_t data[blk_size]; - //assert(cpuXC->copySrcAddr); - int offset = dest & (blk_size - 1); - - // Make sure block doesn't span page - if (no_warn && - (dest & PageMask) != ((dest + blk_size) & PageMask) && - (dest >> 40) != 0xfffffc) { - no_warn = false; - warn("Copied block destination spans pages %x. ", dest); - } - - memReq->reset(dest & ~(blk_size -1), blk_size); - // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(memReq); - - if (fault == NoFault) { - Addr dest_addr = memReq->paddr + offset; - // Need to read straight from memory since we have more than 8 bytes. - memReq->paddr = cpuXC->copySrcPhysAddr; - cpuXC->mem->read(memReq, data); - memReq->paddr = dest_addr; - cpuXC->mem->write(memReq, data); - memReq->cmd = Copy; - memReq->completionEvent = NULL; - memReq->paddr = cpuXC->copySrcPhysAddr; - memReq->dest = dest_addr; - memReq->size = 64; - memReq->time = curTick; - memReq->flags &= ~INST_READ; - } - else - assert(!fault->isAlignmentFault()); - - return fault; + panic("Unimplemented!"); } -// precise architected memory state accessor macros template <class T> Fault CheckerCPU::read(Addr addr, T &data, unsigned flags) @@ -280,17 +175,15 @@ CheckerCPU::read(Addr addr, T &data, unsigned flags) memReq->reset(addr, sizeof(T), flags); // translate to physical address - // Should I probe the DTB? Or should I just take the physical address - // and assume correct translation? translateDataReadReq(memReq); - // if we have a cache, do cache access too memReq->cmd = Read; memReq->completionEvent = NULL; memReq->time = curTick; memReq->flags &= ~INST_READ; if (!(memReq->flags & UNCACHEABLE)) { + // Access memory to see if we have the same data cpuXC->read(memReq, data); } else { // Assume the data is correct if it's an uncached access @@ -350,29 +243,34 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) // translate to physical address cpuXC->translateDataWriteReq(memReq); - if ((!(unverifiedReq->flags & LOCKED) || - ((unverifiedReq->flags & LOCKED) && - unverifiedReq->result == 1)) && - !(unverifiedReq->flags & UNCACHEABLE)) { - // do functional access -// cpuXC->read(memReq, data); - - memReq->cmd = Write; -// memcpy(memReq->data,(uint8_t *)&data,memReq->size); - T inst_data; - memcpy(&inst_data, unverifiedReq->data, sizeof(T)); + // 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->flags & UNCACHEABLE) && + (!(unverifiedReq->flags & LOCKED) || + ((unverifiedReq->flags & LOCKED) && + unverifiedReq->result == 1))) { +#if 0 + memReq->cmd = Read; memReq->completionEvent = NULL; memReq->time = curTick; memReq->flags &= ~INST_READ; + cpuXC->read(memReq, inst_data); +#endif + T inst_data; + memcpy(&inst_data, unverifiedReq->data, sizeof(T)); - // Hard to verify this as the data writes back after the - // instruction commits. May only be able to check that the - // value produced from execute() matches the value produced - // from the instruction's first execution. if (data != inst_data) { - warn("Store value does not match value in memory! " + warn("%lli: Store value does not match value in memory! " "Instruction: %#x, memory: %#x", - inst_data, data); + curTick, inst_data, data); handleError(); } } @@ -436,19 +334,6 @@ CheckerCPU::dbg_vtophys(Addr addr) } #endif // FULL_SYSTEM -#if FULL_SYSTEM -void -CheckerCPU::post_interrupt(int int_num, int index) -{ - BaseCPU::post_interrupt(int_num, index); - - if (cpuXC->status() == ExecContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); - cpuXC->activate(); - } -} -#endif // FULL_SYSTEM - bool CheckerCPU::translateInstReq(MemReqPtr &req) { @@ -466,15 +351,16 @@ CheckerCPU::translateDataReadReq(MemReqPtr &req) cpuXC->translateDataReadReq(req); if (req->vaddr != unverifiedReq->vaddr) { - warn("Request virtual addresses do not match! Inst: %#x, checker:" - " %#x", - unverifiedReq->vaddr, req->vaddr); + warn("%lli: Request virtual addresses do not match! Inst: %#x, " + "checker: %#x", + curTick, unverifiedReq->vaddr, req->vaddr); + handleError(); } req->paddr = unverifiedReq->paddr; if (checkFlags(req)) { - warn("Request flags do not match! Inst: %#x, checker: %#x", - unverifiedReq->flags, req->flags); + warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", + curTick, unverifiedReq->flags, req->flags); handleError(); } } @@ -485,15 +371,16 @@ CheckerCPU::translateDataWriteReq(MemReqPtr &req) cpuXC->translateDataWriteReq(req); if (req->vaddr != unverifiedReq->vaddr) { - warn("Request virtual addresses do not match! Inst: %#x, checker:" - " %#x", - unverifiedReq->vaddr, req->vaddr); + warn("%lli: Request virtual addresses do not match! Inst: %#x, " + "checker: %#x", + curTick, unverifiedReq->vaddr, req->vaddr); + handleError(); } req->paddr = unverifiedReq->paddr; if (checkFlags(req)) { - warn("Request flags do not match! Inst: %#x, checker: %#x", - unverifiedReq->flags, req->flags); + warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", + curTick, unverifiedReq->flags, req->flags); handleError(); } } @@ -512,13 +399,17 @@ CheckerCPU::checkFlags(MemReqPtr &req) } } -/* start simulation, program loaded, processor precise state initialized */ template <class DynInstPtr> void Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) { DynInstPtr inst; + // Either check this instruction, or add it to a list of + // instructions waiting to be checked. Instructions must be + // checked in program order, so if a store has committed yet not + // completed, there may be some instructions that are waiting + // behind it that have completed and must be checked. if (!instList.empty()) { if (youngestSN < completed_inst->seqNum) { DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", @@ -547,16 +438,17 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) inst = completed_inst; youngestSN = completed_inst->seqNum; } else { -// panic("SN already seen yet the list is empty!"); return; } } } + // Try to check all instructions that are completed, ending if we + // run out of instructions to check or if an instruction is not + // yet completed. while (1) { DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", inst->seqNum, inst->readPC()); -// verifyInst = completed_inst; unverifiedResult.integer = inst->readIntResult(); unverifiedReq = inst->req; numCycles++; @@ -569,15 +461,9 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) cpuXC->setFloatRegDouble(ZeroReg, 0.0); #endif // TARGET_ALPHA - // Try to fetch an instruction - - // set up memory request for instruction fetch -#if FULL_SYSTEM -#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 -#else -#define IFETCH_FLAGS(pc) 0 -#endif - + // Check if any recent PC changes match up with anything we + // expect to happen. This is mostly to check if traps or + // PC-based events have occurred in both the checker and CPU. if (changedPC) { DPRINTF(Checker, "Changed PC recently to %#x\n", cpuXC->readPC()); @@ -585,9 +471,9 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) if (newPC == cpuXC->readPC()) { DPRINTF(Checker, "Changed PC matches expected PC\n"); } else { - warn("Changed PC does not match expected PC, changed: %#x, " - "expected: %#x", - cpuXC->readPC(), newPC); + warn("%lli: Changed PC does not match expected PC, " + "changed: %#x, expected: %#x", + curTick, cpuXC->readPC(), newPC); handleError(); } willChangePC = false; @@ -600,6 +486,15 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) changedNextPC = false; } + // Try to fetch the instruction + +#if FULL_SYSTEM +#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 +#else +#define IFETCH_FLAGS(pc) 0 +#endif + + // set up memory request for instruction fetch memReq->cmd = Read; memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t), IFETCH_FLAGS(cpuXC->readPC())); @@ -608,8 +503,13 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) if (!succeeded) { if (inst->getFault() == NoFault) { - warn("Instruction PC %#x was not found in the ITB!", - cpuXC->readPC()); + // In this case the instruction was not a dummy + // instruction carrying an ITB fault. In the single + // threaded case the ITB should still be able to + // translate this instruction; in the SMT case it's + // possible that its ITB entry was kicked out. + warn("%lli: Instruction PC %#x was not found in the ITB!", + curTick, cpuXC->readPC()); handleError(); // go to the next instruction @@ -618,20 +518,18 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) return; } else { + // The instruction is carrying an ITB fault. Handle + // the fault and see if our results match the CPU on + // the next tick(). fault = inst->getFault(); } } if (fault == NoFault) { -// fault = cpuXC->mem->read(memReq, machInst); cpuXC->mem->read(memReq, machInst); - // If we've got a valid instruction (i.e., no fault on instruction - // fetch), then execute it. - - // keep an instruction count + // keep an instruction count numInst++; -// numInsts++; // decode the instruction machInst = gtoh(machInst); @@ -639,7 +537,8 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) // Checks both the machine instruction and the PC. validateInst(inst); - curStaticInst = StaticInst::decode(makeExtMI(machInst, cpuXC->readPC())); + curStaticInst = StaticInst::decode(makeExtMI(machInst, + cpuXC->readPC())); #if FULL_SYSTEM cpuXC->setInst(machInst); @@ -660,10 +559,6 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) // Checks to make sure instrution results are correct. validateExecution(inst); -// if (curStaticInst->isMemRef()) { -// numMemRefs++; -// } - if (curStaticInst->isLoad()) { ++numLoad; } @@ -693,6 +588,9 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) } #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 { @@ -707,10 +605,12 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) } #endif - // Checks PC, next PC. Optionally can check all registers. (Or just those + // @todo: Optionally can check all registers. (Or just those // that have been modified). validateState(); + // Continue verifying instructions if there's another completed + // instruction waiting to be verified. if (instList.empty()) { break; } else if (instList.front()->isCompleted()) { @@ -726,7 +626,6 @@ template <class DynInstPtr> void Checker<DynInstPtr>::switchOut(Sampler *s) { - sampler = s; instList.clear(); } @@ -734,15 +633,6 @@ template <class DynInstPtr> void Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) { -// BaseCPU::takeOverFrom(oldCPU); - - // if any of this CPU's ExecContexts are active, mark the CPU as - // running and schedule its tick event. -/* - for (int i = 0; i < execContexts.size(); ++i) { - ExecContext *xc = execContexts[i]; - } -*/ } template <class DynInstPtr> @@ -750,20 +640,22 @@ void Checker<DynInstPtr>::validateInst(DynInstPtr &inst) { if (inst->readPC() != cpuXC->readPC()) { - warn("PCs do not match! Inst: %#x, checker: %#x", - inst->readPC(), cpuXC->readPC()); + warn("%lli: PCs do not match! Inst: %#x, checker: %#x", + curTick, inst->readPC(), cpuXC->readPC()); if (changedPC) { - warn("Changed PCs recently, may not be an error"); + warn("%lli: Changed PCs recently, may not be an error", + curTick); } else { handleError(); } } - if (static_cast<MachInst>(inst->staticInst->machInst) != - machInst) { - warn("Binary instructions do not match! Inst: %#x, checker: %#x", - static_cast<MachInst>(inst->staticInst->machInst), - machInst); + MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); + + if (mi != machInst) { + warn("%lli: Binary instructions do not match! Inst: %#x, " + "checker: %#x", + curTick, mi, machInst); handleError(); } } @@ -773,10 +665,11 @@ void Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) { if (inst->numDestRegs()) { + // @todo: Support more destination registers. if (inst->isUnverifiable()) { - // @todo: Support more destination registers. - // Grab the result from the instruction and write it to the - // register. + // Unverifiable instructions assume they were executed + // properly by the CPU. Grab the result from the + // instruction and write it to the register. RegIndex idx = inst->destRegIdx(0); if (idx < TheISA::FP_Base_DepTag) { cpuXC->setIntReg(idx, inst->readIntResult()); @@ -786,16 +679,17 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) cpuXC->setMiscReg(idx, inst->readIntResult()); } } else if (result.integer != inst->readIntResult()) { - warn("Instruction results do not match! (May not be integer results) " - "Inst: %#x, checker: %#x", - inst->readIntResult(), result.integer); + warn("%lli: Instruction results do not match! (Results may not " + "actually be integers) Inst: %#x, checker: %#x", + curTick, inst->readIntResult(), result.integer); handleError(); } } if (inst->readNextPC() != cpuXC->readNextPC()) { - warn("Instruction next PCs do not match! Inst: %#x, checker: %#x", - inst->readNextPC(), cpuXC->readNextPC()); + warn("%lli: Instruction next PCs do not match! Inst: %#x, " + "checker: %#x", + curTick, inst->readNextPC(), cpuXC->readNextPC()); handleError(); } @@ -810,9 +704,10 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) if (inst->xcBase()->readMiscReg(misc_reg_idx) != cpuXC->readMiscReg(misc_reg_idx)) { - warn("Misc reg idx %i (side effect) does not match! Inst: %#x, " - "checker: %#x", - misc_reg_idx, inst->xcBase()->readMiscReg(misc_reg_idx), + warn("%lli: Misc reg idx %i (side effect) does not match! " + "Inst: %#x, checker: %#x", + curTick, misc_reg_idx, + inst->xcBase()->readMiscReg(misc_reg_idx), cpuXC->readMiscReg(misc_reg_idx)); handleError(); } diff --git a/cpu/checker/cpu.hh b/cpu/checker/cpu.hh index 678e888df..37fe59d95 100644 --- a/cpu/checker/cpu.hh +++ b/cpu/checker/cpu.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,7 +39,6 @@ #include "cpu/base_dyn_inst.hh" #include "cpu/cpu_exec_context.hh" #include "cpu/pc_event.hh" -#include "cpu/sampler/sampler.hh" #include "cpu/static_inst.hh" #include "sim/eventq.hh" @@ -63,6 +62,7 @@ class BaseDynInst; class ExecContext; class MemInterface; class Checkpoint; +class Sampler; class CheckerCPU : public BaseCPU { @@ -86,8 +86,6 @@ class CheckerCPU : public BaseCPU }; public: - void post_interrupt(int int_num, int index); - CheckerCPU(Params *p); virtual ~CheckerCPU(); @@ -111,8 +109,6 @@ class CheckerCPU : public BaseCPU #if FULL_SYSTEM Addr dbg_vtophys(Addr addr); - - bool interval_stats; #endif union Result { @@ -129,11 +125,6 @@ class CheckerCPU : public BaseCPU // Refcounted pointer to the one memory request. MemReqPtr memReq; - // Pointer to the sampler that is telling us to switchover. - // Used to signal the completion of the pipe drain and schedule - // the next switchover - Sampler *sampler; - StaticInstPtr curStaticInst; // number of simulated instructions @@ -284,6 +275,7 @@ class CheckerCPU : public BaseCPU bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } #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() { } #endif @@ -307,8 +299,6 @@ class CheckerCPU : public BaseCPU bool exitOnError; InstSeqNum youngestSN; -// std::map<Addr, uint64_t> storeBuff; -// typedef std::map<Addr, uint64_t>::iterator map_it; }; template <class DynInstPtr> diff --git a/cpu/checker/exec_context.hh b/cpu/checker/exec_context.hh index 4843d1cf0..38784867d 100644 --- a/cpu/checker/exec_context.hh +++ b/cpu/checker/exec_context.hh @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ + #ifndef __CPU_CHECKER_EXEC_CONTEXT_HH__ #define __CPU_CHECKER_EXEC_CONTEXT_HH__ @@ -6,6 +34,9 @@ #include "cpu/exec_context.hh" class EndQuiesceEvent; +namespace Kernel { + class Statistics; +}; template <class XC> class CheckerExecContext : public ExecContext @@ -13,7 +44,8 @@ class CheckerExecContext : public ExecContext public: CheckerExecContext(XC *actual_xc, CheckerCPU *checker_cpu) - : actualXC(actual_xc), checkerXC(checker_cpu->cpuXC), checkerCPU(checker_cpu) + : actualXC(actual_xc), checkerXC(checker_cpu->cpuXC), + checkerCPU(checker_cpu) { } private: @@ -43,6 +75,8 @@ class CheckerExecContext : public ExecContext AlphaITB *getITBPtr() { return actualXC->getITBPtr(); } AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); } + + Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); } #else Process *getProcessPtr() { return actualXC->getProcessPtr(); } #endif @@ -50,8 +84,10 @@ class CheckerExecContext : public ExecContext Status status() const { return actualXC->status(); } void setStatus(Status new_status) - { actualXC->setStatus(new_status); - checkerXC->setStatus(new_status); } + { + actualXC->setStatus(new_status); + checkerXC->setStatus(new_status); + } /// Set the status to Active. Optional delay indicates number of /// cycles to wait before beginning execution. @@ -216,8 +252,6 @@ class CheckerExecContext : public ExecContext actualXC->setSyscallReturn(return_value); } -// void syscall() { actualXC->syscall(); } - Counter readFuncExeInst() { return actualXC->readFuncExeInst(); } #endif }; diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc index 24de6d450..78ce058e8 100644 --- a/cpu/cpu_exec_context.cc +++ b/cpu/cpu_exec_context.cc @@ -188,7 +188,8 @@ CPUExecContext::serialize(ostream &os) if (quiesceEvent->scheduled()) quiesceEndTick = quiesceEvent->when(); SERIALIZE_SCALAR(quiesceEndTick); - + if (kernelStats) + kernelStats->serialize(os); #endif } @@ -207,6 +208,8 @@ CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(quiesceEndTick); if (quiesceEndTick) quiesceEvent->schedule(quiesceEndTick); + if (kernelStats) + kernelStats->unserialize(cp, section); #endif } @@ -275,6 +278,10 @@ CPUExecContext::halt() void CPUExecContext::regStats(const string &name) { +#if FULL_SYSTEM + kernelStats = new Kernel::Statistics(system); + kernelStats->regStats(name + ".kern"); +#endif } void diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh index cac006925..3d1428933 100644 --- a/cpu/cpu_exec_context.hh +++ b/cpu/cpu_exec_context.hh @@ -53,6 +53,10 @@ class FunctionProfile; class ProfileNode; class MemoryController; +namespace Kernel { + class Statistics; +}; + #else // !FULL_SYSTEM #include "sim/process.hh" @@ -147,6 +151,9 @@ class CPUExecContext void profileSample(); + Kernel::Statistics *getKernelStats() { return kernelStats; } + + Kernel::Statistics *kernelStats; #else Process *process; diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 7bd7d5682..e1f1016e5 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -48,6 +48,9 @@ class FunctionalMemory; class PhysicalMemory; class Process; class System; +namespace Kernel { + class Statistics; +}; class ExecContext { @@ -98,6 +101,8 @@ class ExecContext virtual AlphaITB *getITBPtr() = 0; virtual AlphaDTB * getDTBPtr() = 0; + + virtual Kernel::Statistics *getKernelStats() = 0; #else virtual Process *getProcessPtr() = 0; #endif @@ -243,6 +248,8 @@ class ProxyExecContext : public ExecContext AlphaITB *getITBPtr() { return actualXC->getITBPtr(); } AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); } + + Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); } #else Process *getProcessPtr() { return actualXC->getProcessPtr(); } #endif diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh index 78ad5f7d8..5c89e3462 100644 --- a/cpu/o3/alpha_cpu.hh +++ b/cpu/o3/alpha_cpu.hh @@ -35,6 +35,9 @@ #include "sim/byteswap.hh" class EndQuiesceEvent; +namespace Kernel { + class Statistics; +}; template <class Impl> class AlphaFullCPU : public FullO3CPU<Impl> @@ -60,11 +63,6 @@ class AlphaFullCPU : public FullO3CPU<Impl> O3ThreadState<Impl> *thread; - Tick lastActivate; - Tick lastSuspend; - - EndQuiesceEvent *quiesceEvent; - virtual BaseCPU *getCpuPtr() { return cpu; } virtual void setCpuId(int id) { cpu->cpu_id = id; } @@ -81,6 +79,9 @@ class AlphaFullCPU : public FullO3CPU<Impl> virtual AlphaITB *getITBPtr() { return cpu->itb; } virtual AlphaDTB * getDTBPtr() { return cpu->dtb; } + + virtual Kernel::Statistics *getKernelStats() + { return thread->kernelStats; } #else virtual Process *getProcessPtr() { return thread->process; } #endif diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh index 58b2b3548..91cd3d9e6 100644 --- a/cpu/o3/alpha_cpu_impl.hh +++ b/cpu/o3/alpha_cpu_impl.hh @@ -31,7 +31,6 @@ #include "base/statistics.hh" #include "base/timebuf.hh" #include "cpu/checker/exec_context.hh" -#include "cpu/quiesce_event.hh" #include "mem/mem_interface.hh" #include "sim/sim_events.hh" #include "sim/stats.hh" @@ -44,6 +43,8 @@ #if FULL_SYSTEM #include "arch/alpha/osfpal.hh" #include "arch/isa_traits.hh" +#include "cpu/quiesce_event.hh" +#include "kern/kernel_stats.hh" #endif using namespace TheISA; @@ -101,11 +102,12 @@ AlphaFullCPU<Impl>::AlphaFullCPU(Params *params) alpha_xc_proxy->cpu = this; alpha_xc_proxy->thread = this->thread[i]; - alpha_xc_proxy->quiesceEvent = +#if FULL_SYSTEM + this->thread[i]->quiesceEvent = new EndQuiesceEvent(xc_proxy); - alpha_xc_proxy->lastActivate = 0; - alpha_xc_proxy->lastSuspend = 0; - + this->thread[i]->lastActivate = 0; + this->thread[i]->lastSuspend = 0; +#endif this->thread[i]->xcProxy = xc_proxy; this->execContexts.push_back(xc_proxy); @@ -181,6 +183,9 @@ AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context) if (thread->quiesceEvent) { thread->quiesceEvent->xc = this; } + + // Transfer kernel stats from one CPU to the other. + thread->kernelStats = old_context->getKernelStats(); // storeCondFailures = 0; cpu->lockFlag = false; #endif @@ -200,7 +205,9 @@ AlphaFullCPU<Impl>::AlphaXC::activate(int delay) if (thread->status() == ExecContext::Active) return; - lastActivate = curTick; +#if FULL_SYSTEM + thread->lastActivate = curTick; +#endif if (thread->status() == ExecContext::Unallocated) { cpu->activateWhenReady(thread->tid); @@ -222,8 +229,10 @@ AlphaFullCPU<Impl>::AlphaXC::suspend() if (thread->status() == ExecContext::Suspended) return; - lastActivate = curTick; - lastSuspend = curTick; +#if FULL_SYSTEM + thread->lastActivate = curTick; + thread->lastSuspend = curTick; +#endif /* #if FULL_SYSTEM // Don't change the status from active if there are pending interrupts @@ -266,38 +275,55 @@ AlphaFullCPU<Impl>::AlphaXC::halt() template <class Impl> void AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name) -{} +{ +#if FULL_SYSTEM + thread->kernelStats = new Kernel::Statistics(cpu->system); + thread->kernelStats->regStats(name + ".kern"); +#endif +} template <class Impl> void AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os) -{} +{ +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->serialize(os); +#endif + +} template <class Impl> void AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string §ion) -{} +{ +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->unserialize(cp, section); +#endif + +} #if FULL_SYSTEM template <class Impl> EndQuiesceEvent * AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent() { - return quiesceEvent; + return thread->quiesceEvent; } template <class Impl> Tick AlphaFullCPU<Impl>::AlphaXC::readLastActivate() { - return lastActivate; + return thread->lastActivate; } template <class Impl> Tick AlphaFullCPU<Impl>::AlphaXC::readLastSuspend() { - return lastSuspend; + return thread->lastSuspend; } template <class Impl> @@ -595,7 +621,7 @@ AlphaFullCPU<Impl>::hwrei(unsigned tid) // Need to clear the lock flag upon returning from an interrupt. this->lockFlag = false; - this->kernelStats->hwrei(); + this->thread[tid]->kernelStats->hwrei(); this->checkInterrupts = true; @@ -607,9 +633,9 @@ template <class Impl> bool AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid) { - if (this->kernelStats) - this->kernelStats->callpal(palFunc, - this->execContexts[tid]); + if (this->thread[tid]->kernelStats) + this->thread[tid]->kernelStats->callpal(palFunc, + this->execContexts[tid]); switch (palFunc) { case PAL::halt: diff --git a/cpu/o3/iew_impl.hh b/cpu/o3/iew_impl.hh index cf28f2efc..b0137d7fc 100644 --- a/cpu/o3/iew_impl.hh +++ b/cpu/o3/iew_impl.hh @@ -1232,13 +1232,14 @@ DefaultIEW<Impl>::executeInsts() #endif // Execute/writeback any instructions that are available. + int insts_to_execute = fromIssue->size; int inst_num = 0; - for ( ; inst_num < issueWidth && fromIssue->insts[inst_num]; + for (; inst_num < insts_to_execute; ++inst_num) { DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); - DynInstPtr inst = fromIssue->insts[inst_num]; + DynInstPtr inst = instQueue.getInstToExecute(); DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n", inst->readPC(), inst->threadNumber,inst->seqNum); diff --git a/cpu/o3/inst_queue.hh b/cpu/o3/inst_queue.hh index 6bdf4ddc2..518de73d9 100644 --- a/cpu/o3/inst_queue.hh +++ b/cpu/o3/inst_queue.hh @@ -171,6 +171,8 @@ class InstructionQueue */ void insertBarrier(DynInstPtr &barr_inst); + DynInstPtr getInstToExecute(); + /** * Records the instruction as the producer of a register without * adding it to the rest of the IQ. @@ -272,6 +274,8 @@ class InstructionQueue /** List of all the instructions in the IQ (some of which may be issued). */ std::list<DynInstPtr> instList[Impl::MaxThreads]; + std::list<DynInstPtr> instsToExecute; + /** * Struct for comparing entries to be added to the priority queue. This * gives reverse ordering to the instructions in terms of sequence diff --git a/cpu/o3/inst_queue_impl.hh b/cpu/o3/inst_queue_impl.hh index 71541b4f8..f1dc4e01f 100644 --- a/cpu/o3/inst_queue_impl.hh +++ b/cpu/o3/inst_queue_impl.hh @@ -589,6 +589,16 @@ InstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst) } template <class Impl> +typename Impl::DynInstPtr +InstructionQueue<Impl>::getInstToExecute() +{ + assert(!instsToExecute.empty()); + DynInstPtr inst = instsToExecute.front(); + instsToExecute.pop_front(); + return inst; +} + +template <class Impl> void InstructionQueue<Impl>::addToOrderList(OpClass op_class) { @@ -662,9 +672,11 @@ InstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx) // @todo: This could break if there's multiple multi-cycle ops // finishing on this cycle. Maybe implement something like // instToCommit in iew_impl.hh. - int &size = issueToExecuteQueue->access(0)->size; + issueToExecuteQueue->access(0)->size++; + instsToExecute.push_back(inst); +// int &size = issueToExecuteQueue->access(0)->size; - issueToExecuteQueue->access(0)->insts[size++] = inst; +// issueToExecuteQueue->access(0)->insts[size++] = inst; } // @todo: Figure out a better way to remove the squashed items from the @@ -690,9 +702,8 @@ InstructionQueue<Impl>::scheduleReadyInsts() ListOrderIt order_it = listOrder.begin(); ListOrderIt order_end_it = listOrder.end(); int total_issued = 0; - int exec_queue_slot = i2e_info->size; - while (exec_queue_slot < totalWidth && total_issued < totalWidth && + while (total_issued < totalWidth && order_it != order_end_it) { OpClass op_class = (*order_it).queueType; @@ -733,8 +744,9 @@ InstructionQueue<Impl>::scheduleReadyInsts() if (idx == -2 || idx != -1) { if (op_latency == 1) { - i2e_info->insts[exec_queue_slot++] = issuing_inst; +// i2e_info->insts[exec_queue_slot++] = issuing_inst; i2e_info->size++; + instsToExecute.push_back(issuing_inst); // Add the FU onto the list of FU's to be freed next // cycle if we used one. diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh index 7e12e75e5..5af2b02b2 100644 --- a/cpu/ozone/cpu.hh +++ b/cpu/ozone/cpu.hh @@ -57,6 +57,10 @@ class Sampler; class RemoteGDB; class GDBListener; +namespace Kernel { + class Statistics; +}; + #else class Process; @@ -116,6 +120,8 @@ class OzoneCPU : public BaseCPU AlphaITB *getITBPtr() { return cpu->itb; } AlphaDTB * getDTBPtr() { return cpu->dtb; } + + Kernel::Statistics *getKernelStats() { return thread->kernelStats; } #else Process *getProcessPtr() { return thread->process; } #endif @@ -238,14 +244,7 @@ class OzoneCPU : public BaseCPU private: OzoneThreadState<Impl> thread; -/* - // Squash event for when the XC needs to squash all inflight instructions. - struct XCSquashEvent : public Event - { - void process(); - const char *description(); - }; -*/ + public: // main simulation loop (one cycle) void tick(); @@ -288,7 +287,6 @@ class OzoneCPU : public BaseCPU void trace_data(T data); public: - // enum Status { Running, Idle, @@ -325,8 +323,6 @@ class OzoneCPU : public BaseCPU int readCpuId() { return cpuId; } -// FunctionalMemory *getMemPtr() { return mem; } - int cpuId; void switchOut(Sampler *sampler); @@ -369,8 +365,6 @@ class OzoneCPU : public BaseCPU Status status() const { return _status; } void setStatus(Status new_status) { _status = new_status; } - // Not sure what an activate() call on the CPU's proxy XC would mean... - virtual void activateContext(int thread_num, int delay); virtual void suspendContext(int thread_num); virtual void deallocateContext(int thread_num); @@ -384,7 +378,6 @@ class OzoneCPU : public BaseCPU public: Counter numInst; Counter startNumInst; -// Stats::Scalar<> numInsts; virtual Counter totalInstructions() const { @@ -392,9 +385,6 @@ class OzoneCPU : public BaseCPU } private: - // number of simulated memory references -// Stats::Scalar<> numMemRefs; - // number of simulated loads Counter numLoad; Counter startNumLoad; @@ -472,7 +462,6 @@ class OzoneCPU : public BaseCPU template <class T> Fault read(MemReqPtr &req, T &data) { -// panic("CPU READ NOT IMPLEMENTED W/NEW MEMORY\n"); #if 0 #if FULL_SYSTEM && defined(TARGET_ALPHA) if (req->flags & LOCKED) { @@ -483,7 +472,6 @@ class OzoneCPU : public BaseCPU #endif Fault error; if (req->flags & LOCKED) { -// lockAddr = req->paddr; lockAddrList.insert(req->paddr); lockFlag = true; } @@ -558,7 +546,7 @@ class OzoneCPU : public BaseCPU if (req->flags & UNCACHEABLE) { req->result = 2; } else { - if (this->lockFlag/* && this->lockAddr == req->paddr*/) { + if (this->lockFlag) { if (lockAddrList.find(req->paddr) != lockAddrList.end()) { req->result = 1; diff --git a/cpu/ozone/cpu_impl.hh b/cpu/ozone/cpu_impl.hh index 031b4b145..5675da3a8 100644 --- a/cpu/ozone/cpu_impl.hh +++ b/cpu/ozone/cpu_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 The Regents of The University of Michigan + * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <cstdio> -#include <cstdlib> +//#include <cstdio> +//#include <cstdlib> #include "arch/isa_traits.hh" // For MachInst #include "base/trace.hh" @@ -39,7 +39,7 @@ #include "cpu/ozone/cpu.hh" #include "cpu/quiesce_event.hh" #include "cpu/static_inst.hh" -#include "mem/base_mem.hh" +//#include "mem/base_mem.hh" #include "mem/mem_interface.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" @@ -50,7 +50,7 @@ #include "arch/alpha/tlb.hh" #include "arch/vtophys.hh" #include "base/callback.hh" -#include "base/remote_gdb.hh" +//#include "base/remote_gdb.hh" #include "cpu/profile.hh" #include "kern/kernel_stats.hh" #include "mem/functional/memory_control.hh" @@ -94,80 +94,26 @@ OzoneCPU<Impl>::TickEvent::description() { return "OzoneCPU tick event"; } -/* -template <class Impl> -OzoneCPU<Impl>::ICacheCompletionEvent::ICacheCompletionEvent(OzoneCPU *_cpu) - : Event(&mainEventQueue), - cpu(_cpu) -{ -} - -template <class Impl> -void -OzoneCPU<Impl>::ICacheCompletionEvent::process() -{ - cpu->processICacheCompletion(); -} - -template <class Impl> -const char * -OzoneCPU<Impl>::ICacheCompletionEvent::description() -{ - return "OzoneCPU I-cache completion event"; -} - -template <class Impl> -OzoneCPU<Impl>::DCacheCompletionEvent:: -DCacheCompletionEvent(OzoneCPU *_cpu, - DynInstPtr &_inst, - DCacheCompEventIt &_dcceIt) - : Event(&mainEventQueue), - cpu(_cpu), - inst(_inst), - dcceIt(_dcceIt) -{ - this->setFlags(Event::AutoDelete); -} - -template <class Impl> -void -OzoneCPU<Impl>::DCacheCompletionEvent::process() -{ - inst->setCompleted(); - - // Maybe remove the EA from the list of addrs? - cpu->eaList.clearAddr(inst->seqNum, inst->getEA()); - cpu->dCacheCompList.erase(this->dcceIt); -} template <class Impl> -const char * -OzoneCPU<Impl>::DCacheCompletionEvent::description() -{ - return "OzoneCPU D-cache completion event"; -} -*/ -template <class Impl> OzoneCPU<Impl>::OzoneCPU(Params *p) #if FULL_SYSTEM - : BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width), mem(p->mem), + : BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width), + mem(p->mem), #else : BaseCPU(p), thread(this, 0, p->workload[0], 0), tickEvent(this, p->width), mem(p->workload[0]->getMemory()), #endif comm(5, 5) { - if (p->checker) { - BaseCPU *temp_checker = p->checker; - checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); - } else { - checker = NULL; - } frontEnd = new FrontEnd(p); backEnd = new BackEnd(p); _status = Idle; - if (checker) { + + if (p->checker) { + BaseCPU *temp_checker = p->checker; + checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); checker->setMemory(mem); #if FULL_SYSTEM checker->setSystem(p->system); @@ -176,19 +122,18 @@ OzoneCPU<Impl>::OzoneCPU(Params *p) thread.xcProxy = checkerXC; xcProxy = checkerXC; } else { + checker = NULL; thread.xcProxy = &ozoneXC; xcProxy = &ozoneXC; } - thread.inSyscall = false; - ozoneXC.cpu = this; ozoneXC.thread = &thread; + thread.inSyscall = false; + thread.setStatus(ExecContext::Suspended); #if FULL_SYSTEM -// xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); - /***** All thread state stuff *****/ thread.cpu = this; thread.tid = 0; @@ -217,31 +162,15 @@ OzoneCPU<Impl>::OzoneCPU(Params *p) thread.profileNode = &dummyNode; thread.profilePC = 3; #else -// xc = new ExecContext(this, /* thread_num */ 0, p->workload[0], /* asid */ 0); thread.cpu = this; thread.tid = 0; thread.process = p->workload[0]; -// thread.mem = thread.process->getMemory(); thread.asid = 0; #endif // !FULL_SYSTEM -/* - icacheInterface = p->icache_interface; - dcacheInterface = p->dcache_interface; - - cacheMemReq = new MemReq(); - cacheMemReq->xc = xc; - cacheMemReq->asid = 0; - cacheMemReq->data = new uint8_t[64]; -*/ + numInst = 0; startNumInst = 0; -/* numLoad = 0; - startNumLoad = 0; - lastIcacheStall = 0; - lastDcacheStall = 0; - issueWidth = p->issueWidth; -*/ execContexts.push_back(xcProxy); frontEnd->setCPU(this); @@ -286,47 +215,7 @@ template <class Impl> OzoneCPU<Impl>::~OzoneCPU() { } -/* -template <class Impl> -void -OzoneCPU<Impl>::copyFromXC() -{ - for (int i = 0; i < TheISA::TotalNumRegs; ++i) { - if (i < TheISA::NumIntRegs) { - renameTable[i]->setIntResult(xc->readIntReg(i)); - } else if (i < TheISA::NumFloatRegs) { - renameTable[i]->setDoubleResult(xc->readFloatRegDouble(i)); - } - } - - DPRINTF(OzoneCPU, "Func Exe inst is: %i\n", xc->func_exe_inst); - backEnd->funcExeInst = xc->func_exe_inst; -// PC = xc->readPC(); -// nextPC = xc->regs.npc; -} - -template <class Impl> -void -OzoneCPU<Impl>::copyToXC() -{ - for (int i = 0; i < TheISA::TotalNumRegs; ++i) { - if (i < TheISA::NumIntRegs) { - xc->setIntReg(i, renameTable[i]->readIntResult()); - } else if (i < TheISA::NumFloatRegs) { - xc->setFloatRegDouble(i, renameTable[i]->readDoubleResult()); - } - } - - this->xc->regs.miscRegs.fpcr = this->regFile.miscRegs[tid].fpcr; - this->xc->regs.miscRegs.uniq = this->regFile.miscRegs[tid].uniq; - this->xc->regs.miscRegs.lock_flag = this->regFile.miscRegs[tid].lock_flag; - this->xc->regs.miscRegs.lock_addr = this->regFile.miscRegs[tid].lock_addr; - xc->func_exe_inst = backEnd->funcExeInst; - xc->regs.pc = PC; - xc->regs.npc = nextPC; -} -*/ template <class Impl> void OzoneCPU<Impl>::switchOut(Sampler *_sampler) @@ -394,7 +283,6 @@ OzoneCPU<Impl>::activateContext(int thread_num, int delay) { // Eventually change this in SMT. assert(thread_num == 0); -// assert(xcProxy); assert(_status == Idle); notIdleFraction++; @@ -410,8 +298,8 @@ OzoneCPU<Impl>::suspendContext(int thread_num) { // Eventually change this in SMT. assert(thread_num == 0); -// assert(xcProxy); - // @todo: Figure out how to initially set the status properly so this is running. + // @todo: Figure out how to initially set the status properly so + // this is running. // assert(_status == Running); notIdleFraction--; unscheduleTickEvent(); @@ -486,14 +374,7 @@ void OzoneCPU<Impl>::init() { BaseCPU::init(); -/* - copyFromXC(); - // ALso copy over PC/nextPC. This isn't normally copied in "copyFromXC()" - // so that the XC doesn't mess up the PC when returning from a syscall. - PC = xc->readPC(); - nextPC = xc->regs.npc; -*/ // Mark this as in syscall so it won't need to squash thread.inSyscall = true; #if FULL_SYSTEM @@ -514,8 +395,6 @@ template <class Impl> void OzoneCPU<Impl>::serialize(std::ostream &os) { - // At this point, all DCacheCompEvents should be processed. - BaseCPU::serialize(os); SERIALIZE_ENUM(_status); nameOut(os, csprintf("%s.xc", name())); @@ -631,31 +510,7 @@ OzoneCPU<Impl>::dbg_vtophys(Addr addr) return vtophys(xcProxy, addr); } #endif // FULL_SYSTEM -/* -template <class Impl> -void -OzoneCPU<Impl>::processICacheCompletion() -{ - switch (status()) { - case IcacheMiss: - DPRINTF(OzoneCPU, "OzoneCPU: Finished Icache miss.\n"); - - icacheStallCycles += curTick - lastIcacheStall; - _status = IcacheMissComplete; - cacheBlkValid = true; -// scheduleTickEvent(1); - break; - case SwitchedOut: - // If this CPU has been switched out due to sampling/warm-up, - // ignore any further status changes (e.g., due to cache - // misses outstanding at the time of the switch). - return; - default: - panic("OzoneCPU::processICacheCompletion: bad state"); - break; - } -} -*/ + #if FULL_SYSTEM template <class Impl> void @@ -663,7 +518,6 @@ OzoneCPU<Impl>::post_interrupt(int int_num, int index) { BaseCPU::post_interrupt(int_num, index); -// if (thread._status == ExecContext::Suspended) { if (_status == Idle) { DPRINTF(IPI,"Suspended Processor awoke\n"); // thread.activate(); @@ -690,9 +544,6 @@ OzoneCPU<Impl>::tick() frontEnd->tick(); backEnd->tick(); - // Do this here? For now the front end will control the PC. -// PC = nextPC; - // check for instruction-count-based events comInstEventQueue[0]->serviceEvents(numInst); @@ -742,11 +593,13 @@ OzoneCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) if (return_value.successful()) { // no error thread.renameTable[SyscallSuccessReg]->setIntResult(0); - thread.renameTable[ReturnValueReg]->setIntResult(return_value.value()); + thread.renameTable[ReturnValueReg]->setIntResult( + return_value.value()); } else { // got an error, return details thread.renameTable[SyscallSuccessReg]->setIntResult((IntReg) -1); - thread.renameTable[ReturnValueReg]->setIntResult(-return_value.value()); + thread.renameTable[ReturnValueReg]->setIntResult( + -return_value.value()); } } #else @@ -756,15 +609,10 @@ OzoneCPU<Impl>::hwrei() { // Need to move this to ISA code // May also need to make this per thread -/* - if (!inPalMode()) - return new UnimplementedOpcodeFault; - thread.setNextPC(thread.readMiscReg(AlphaISA::IPR_EXC_ADDR)); -*/ lockFlag = false; lockAddrList.clear(); - kernelStats->hwrei(); + thread.kernelStats->hwrei(); checkInterrupts = true; @@ -835,7 +683,7 @@ OzoneCPU<Impl>::simPalCheck(int palFunc) { // Need to move this to ISA code // May also need to make this per thread - this->kernelStats->callpal(palFunc, xcProxy); + thread.kernelStats->callpal(palFunc, xcProxy); switch (palFunc) { case PAL::halt: @@ -874,7 +722,6 @@ template <class Impl> void OzoneCPU<Impl>::OzoneXC::setStatus(Status new_status) { -// cpu->_status = new_status; thread->_status = new_status; } @@ -932,6 +779,7 @@ OzoneCPU<Impl>::OzoneXC::takeOverFrom(ExecContext *old_context) setStatus(old_context->status()); copyArchRegs(old_context); setCpuId(old_context->readCpuId()); + #if !FULL_SYSTEM setFuncExeInst(old_context->readFuncExeInst()); #else @@ -944,6 +792,8 @@ OzoneCPU<Impl>::OzoneXC::takeOverFrom(ExecContext *old_context) if (thread->quiesceEvent) { thread->quiesceEvent->xc = this; } + + thread->kernelStats = old_context->getKernelStats(); // storeCondFailures = 0; cpu->lockFlag = false; #endif @@ -954,7 +804,12 @@ OzoneCPU<Impl>::OzoneXC::takeOverFrom(ExecContext *old_context) template <class Impl> void OzoneCPU<Impl>::OzoneXC::regStats(const std::string &name) -{ } +{ +#if FULL_SYSTEM + thread->kernelStats = new Kernel::Statistics(cpu->system); + thread->kernelStats->regStats(name + ".kern"); +#endif +} template <class Impl> void diff --git a/cpu/ozone/dyn_inst.hh b/cpu/ozone/dyn_inst.hh index f251c28ea..5d48bb361 100644 --- a/cpu/ozone/dyn_inst.hh +++ b/cpu/ozone/dyn_inst.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 The Regents of The University of Michigan + * Copyright (c) 2005-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,8 +52,6 @@ class OzoneDynInst : public BaseDynInst<Impl> // Typedef for DynInstPtr. This is really just a RefCountingPtr<OoODynInst>. typedef typename Impl::DynInstPtr DynInstPtr; -// typedef typename Impl::BranchPred::BPredInfo BPredInfo; - typedef TheISA::ExtMachInst ExtMachInst; typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; @@ -107,12 +105,6 @@ class OzoneDynInst : public BaseDynInst<Impl> // up. In the future, you only really need a counter. bool memDepReady() { return srcMemInsts.empty(); } -// void setBPredInfo(const BPredInfo &bp_info) { bpInfo = bp_info; } - -// BPredInfo &getBPredInfo() { return bpInfo; } - -// OzoneXC *thread; - private: void initInstPtrs(); @@ -133,20 +125,12 @@ class OzoneDynInst : public BaseDynInst<Impl> */ DynInstPtr prevDestInst[MaxInstSrcRegs]; -// BPredInfo bpInfo; - public: Fault initiateAcc(); Fault completeAcc(); -/* - template <class T> - Fault read(Addr addr, T &data, unsigned flags); - template <class T> - Fault write(T data, Addr addr, unsigned flags, uint64_t *res); -*/ // The register accessor methods provide the index of the // instruction's operand (e.g., 0 or 1), not the architectural // register index, to simplify the implementation of register @@ -244,38 +228,4 @@ class OzoneDynInst : public BaseDynInst<Impl> bool iqItValid; }; -/* -template<class Impl> -template<class T> -inline Fault -OzoneDynInst<Impl>::read(Addr addr, T &data, unsigned flags) -{ - Fault fault = this->cpu->read(addr, data, flags, this); - - if (this->traceData) { - this->traceData->setAddr(addr); - this->traceData->setData(data); - } - - return fault; -} - -template<class Impl> -template<class T> -inline Fault -OzoneDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res) -{ - Fault fault = this->cpu->write(data, addr, flags, res, this); - - this->storeSize = sizeof(T); - this->storeData = data; - - if (this->traceData) { - this->traceData->setAddr(addr); - this->traceData->setData(data); - } - - return fault; -} -*/ #endif // __CPU_OZONE_DYN_INST_HH__ diff --git a/cpu/ozone/dyn_inst_impl.hh b/cpu/ozone/dyn_inst_impl.hh index a7e4460a1..f891ec515 100644 --- a/cpu/ozone/dyn_inst_impl.hh +++ b/cpu/ozone/dyn_inst_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 The Regents of The University of Michigan + * Copyright (c) 2005-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -266,12 +266,7 @@ OzoneDynInst<Impl>::hwrei() this->setNextPC(this->thread->readMiscReg(AlphaISA::IPR_EXC_ADDR)); this->cpu->hwrei(); -/* - this->cpu->kernelStats->hwrei(); - this->cpu->checkInterrupts = true; - this->cpu->lockFlag = false; -*/ // FIXME: XXX check for interrupts? XXX return NoFault; } diff --git a/cpu/ozone/front_end.hh b/cpu/ozone/front_end.hh index 326f7d2c9..dd382491f 100644 --- a/cpu/ozone/front_end.hh +++ b/cpu/ozone/front_end.hh @@ -1,14 +1,39 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ #ifndef __CPU_OZONE_FRONT_END_HH__ #define __CPU_OZONE_FRONT_END_HH__ #include <deque> -//#include "cpu/ozone/cpu.hh" #include "cpu/inst_seq.hh" #include "cpu/o3/bpred_unit.hh" #include "cpu/ozone/rename_table.hh" -//#include "cpu/ozone/thread_state.hh" #include "mem/mem_req.hh" #include "sim/eventq.hh" #include "sim/stats.hh" @@ -132,11 +157,6 @@ class FrontEnd typedef typename Impl::BranchPred BranchPred; - // Typedef for semi-opaque type that holds any information the branch - // predictor needs to update itself. Only two fields are used outside of - // branch predictor, nextPC and isTaken. -// typedef typename BranchPred::BPredInfo BPredInfo; - BranchPred branchPred; class ICacheCompletionEvent : public Event diff --git a/cpu/ozone/front_end_impl.hh b/cpu/ozone/front_end_impl.hh index cd57aeef4..15adae9b4 100644 --- a/cpu/ozone/front_end_impl.hh +++ b/cpu/ozone/front_end_impl.hh @@ -1,3 +1,30 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ #include "arch/faults.hh" #include "arch/isa_traits.hh" @@ -26,14 +53,6 @@ FrontEnd<Impl>::FrontEnd(Params *params) status = Idle; - // Setup branch predictor. - - // Setup Memory Request -/* - memReq = new MemReq(); - memReq->asid = 0; - memReq->data = new uint8_t[64]; -*/ memReq = NULL; // Size of cache block. cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64; @@ -77,7 +96,6 @@ void FrontEnd<Impl>::setXC(ExecContext *xc_ptr) { xc = xc_ptr; -// memReq->xc = xc; } template <class Impl> @@ -321,7 +339,6 @@ FrontEnd<Impl>::tick() break; } - // if (generalizeFetch) { processInst(inst); if (status == SerializeBlocked) { @@ -333,11 +350,6 @@ FrontEnd<Impl>::tick() instBuffer.push_back(inst); ++instBufferSize; ++num_inst; - // } else { - // fetch(num_inst); - // decode(num_inst); - // rename(num_inst); - // } #if FULL_SYSTEM if (inst->isQuiesce()) { @@ -402,10 +414,6 @@ FrontEnd<Impl>::fetchCacheLine() // Translate the instruction request. fault = cpu->translateInstReq(memReq); - // In the case of faults, the fetch stage may need to stall and wait - // on what caused the fetch (ITB or Icache miss). -// assert(fault == NoFault); - // Now do the timing access to see whether or not the instruction // exists within the cache. if (icacheInterface && fault == NoFault) { @@ -466,7 +474,6 @@ FrontEnd<Impl>::processInst(DynInstPtr &inst) Addr inst_PC = inst->readPC(); -// BPredInfo bp_info = branchPred.lookup(inst_PC); if (!inst->isControl()) { inst->setPredTarg(inst->readNextPC()); } else { @@ -482,7 +489,6 @@ FrontEnd<Impl>::processInst(DynInstPtr &inst) "%#x\n", inst->seqNum, inst_PC, next_PC); // inst->setNextPC(next_PC); -// inst->setBPredInfo(bp_info); // Not sure where I should set this PC = next_PC; @@ -535,7 +541,7 @@ void FrontEnd<Impl>::handleFault(Fault &fault) { DPRINTF(FE, "Fault at fetch, telling commit\n"); -// backEnd->fetchFault(fault); + // We're blocked on the back end until it handles this fault. status = TrapPending; @@ -586,9 +592,6 @@ FrontEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC, instBuffer.pop_back(); --instBufferSize; - // Fix up branch predictor if necessary. -// branchPred.undo(inst->getBPredInfo()); - freeRegs+= inst->numDestRegs(); } @@ -607,7 +610,6 @@ FrontEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC, // Clear the icache miss if it's outstanding. if (status == IcacheMissStall && icacheInterface) { DPRINTF(FE, "Squashing outstanding Icache miss.\n"); -// icacheInterface->squash(0); memReq = NULL; } @@ -693,17 +695,9 @@ template <class Impl> bool FrontEnd<Impl>::updateStatus() { -// bool rename_block = freeRegs <= 0; bool serialize_block = !backEnd->robEmpty() || instBufferSize; bool be_block = cpu->decoupledFrontEnd ? false : backEnd->isBlocked(); bool ret_val = false; -/* - // Should already be handled through addFreeRegs function - if (status == RenameBlocked && !rename_block) { - status = Running; - ret_val = true; - } -*/ if (status == SerializeBlocked && !serialize_block) { status = SerializeComplete; @@ -753,10 +747,6 @@ FrontEnd<Impl>::getInstFromCacheline() // PC of inst is not in this cache block if (PC >= (cacheBlkPC + cacheBlkSize) || PC < cacheBlkPC || !cacheBlkValid) { -// DPRINTF(OoOCPU, "OoOCPU: PC is not in this cache block\n"); -// DPRINTF(OoOCPU, "OoOCPU: PC: %#x, cacheBlkPC: %#x, cacheBlkValid: %i", -// PC, cacheBlkPC, cacheBlkValid); -// panic("Instruction not in cache line or cache line invalid!"); return NULL; } diff --git a/cpu/ozone/lw_back_end.hh b/cpu/ozone/lw_back_end.hh index 770b66ad5..1c03ffb73 100644 --- a/cpu/ozone/lw_back_end.hh +++ b/cpu/ozone/lw_back_end.hh @@ -1,3 +1,30 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ #ifndef __CPU_OZONE_LW_BACK_END_HH__ #define __CPU_OZONE_LW_BACK_END_HH__ @@ -238,10 +265,6 @@ class LWBackEnd Counter funcExeInst; private: -// typedef typename Impl::InstQueue InstQueue; - -// InstQueue IQ; - typedef typename Impl::LdstQueue LdstQueue; LdstQueue LSQ; @@ -342,8 +365,6 @@ class LWBackEnd bool exactFullStall; -// bool fetchRedirect[Impl::MaxThreads]; - // number of cycles stalled for D-cache misses /* Stats::Scalar<> dcacheStallCycles; Counter lastDcacheStall; @@ -438,43 +459,6 @@ template <class T> Fault LWBackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx) { -/* memReq->reset(addr, sizeof(T), flags); - - // translate to physical address - Fault fault = cpu->translateDataReadReq(memReq); - - // if we have a cache, do cache access too - if (fault == NoFault && dcacheInterface) { - memReq->cmd = Read; - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~INST_READ; - MemAccessResult result = dcacheInterface->access(memReq); - - // Ugly hack to get an event scheduled *only* if the access is - // a miss. We really should add first-class support for this - // at some point. - if (result != MA_HIT && dcacheInterface->doEvents()) { - // Fix this hack for keeping funcExeInst correct with loads that - // are executed twice. - --funcExeInst; - - memReq->completionEvent = &cacheCompletionEvent; - lastDcacheStall = curTick; -// unscheduleTickEvent(); -// status = DcacheMissStall; - DPRINTF(OzoneCPU, "Dcache miss stall!\n"); - } else { - // do functional access - fault = thread->mem->read(memReq, data); - - } - } -*/ -/* - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) - recordEvent("Uncached Read"); -*/ return LSQ.read(req, data, load_idx); } @@ -483,39 +467,6 @@ template <class T> Fault LWBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx) { -/* - memReq->reset(addr, sizeof(T), flags); - - // translate to physical address - Fault fault = cpu->translateDataWriteReq(memReq); - - if (fault == NoFault && dcacheInterface) { - memReq->cmd = Write; - memcpy(memReq->data,(uint8_t *)&data,memReq->size); - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~INST_READ; - MemAccessResult result = dcacheInterface->access(memReq); - - // Ugly hack to get an event scheduled *only* if the access is - // a miss. We really should add first-class support for this - // at some point. - if (result != MA_HIT && dcacheInterface->doEvents()) { - memReq->completionEvent = &cacheCompletionEvent; - lastDcacheStall = curTick; -// unscheduleTickEvent(); -// status = DcacheMissStall; - DPRINTF(OzoneCPU, "Dcache miss stall!\n"); - } - } - - if (res && (fault == NoFault)) - *res = memReq->result; - */ -/* - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) - recordEvent("Uncached Write"); -*/ return LSQ.write(req, data, store_idx); } diff --git a/cpu/ozone/lw_back_end_impl.hh b/cpu/ozone/lw_back_end_impl.hh index db0872e52..881d6e6b1 100644 --- a/cpu/ozone/lw_back_end_impl.hh +++ b/cpu/ozone/lw_back_end_impl.hh @@ -1,7 +1,34 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ -#include "encumbered/cpu/full/op_class.hh" #include "cpu/checker/cpu.hh" #include "cpu/ozone/lw_back_end.hh" +#include "encumbered/cpu/full/op_class.hh" template <class Impl> void @@ -194,7 +221,6 @@ LWBackEnd<Impl>::LWBackEnd(Params *params) switchedOut = false; switchPending = false; -// IQ.setBE(this); LSQ.setBE(this); // Setup IQ and LSQ with their parameters here. @@ -202,8 +228,6 @@ LWBackEnd<Impl>::LWBackEnd(Params *params) instsToExecute = i2e.getWire(-1); -// IQ.setIssueExecQueue(&i2e); - dispatchWidth = params->dispatchWidth ? params->dispatchWidth : width; issueWidth = params->issueWidth ? params->issueWidth : width; wbWidth = params->wbWidth ? params->wbWidth : width; @@ -538,8 +562,6 @@ LWBackEnd<Impl>::regStats() .desc("ROB Occupancy per cycle") .flags(total | cdf) ; - -// IQ.regStats(); } template <class Impl> @@ -652,17 +674,7 @@ LWBackEnd<Impl>::tick() squashFromTrap(); } else if (xcSquash) { squashFromXC(); - } /*else if (fetchHasFault && robEmpty() && frontEnd->isEmpty() && !LSQ.hasStoresToWB()) { - DPRINTF(BE, "ROB and front end empty, handling fetch fault\n"); - Fault fetch_fault = frontEnd->getFault(); - if (fetch_fault == NoFault) { - DPRINTF(BE, "Fetch no longer has a fault, cancelling out.\n"); - fetchHasFault = false; - } else { - handleFault(fetch_fault); - fetchHasFault = false; - } - }*/ + } #endif if (dispatchStatus != Blocked) { @@ -773,7 +785,8 @@ LWBackEnd<Impl>::dispatchInsts() inst->iqItValid = true; waitingInsts++; } else { - DPRINTF(BE, "Instruction [sn:%lli] ready, addding to exeList.\n", + DPRINTF(BE, "Instruction [sn:%lli] ready, addding to " + "exeList.\n", inst->seqNum); exeList.push(inst); } @@ -784,7 +797,8 @@ LWBackEnd<Impl>::dispatchInsts() inst->setExecuted(); inst->setCanCommit(); } else { - DPRINTF(BE, "Instruction [sn:%lli] ready, addding to exeList.\n", + DPRINTF(BE, "Instruction [sn:%lli] ready, addding to " + "exeList.\n", inst->seqNum); exeList.push(inst); } @@ -993,7 +1007,7 @@ LWBackEnd<Impl>::instToCommit(DynInstPtr &inst) writeback_count[0]++; } - +#if 0 template <class Impl> void LWBackEnd<Impl>::writebackInsts() @@ -1040,7 +1054,7 @@ LWBackEnd<Impl>::writebackInsts() consumer_inst[0]+= consumer_insts; writeback_count[0]+= inst_num; } - +#endif template <class Impl> bool LWBackEnd<Impl>::commitInst(int inst_num) @@ -1219,15 +1233,15 @@ LWBackEnd<Impl>::commitInst(int inst_num) --numInsts; ++thread->funcExeInst; - // Maybe move this to where the fault is handled; if the fault is handled, - // don't try to set this myself as the fault will set it. If not, then - // I set thread->PC = thread->nextPC and thread->nextPC = thread->nextPC + 4. + // Maybe move this to where the fault is handled; if the fault is + // handled, don't try to set this myself as the fault will set it. + // If not, then I set thread->PC = thread->nextPC and + // thread->nextPC = thread->nextPC + 4. thread->setPC(thread->readNextPC()); thread->setNextPC(thread->readNextPC() + sizeof(TheISA::MachInst)); updateComInstStats(inst); // Write the done sequence number here. -// LSQ.commitLoads(inst->seqNum); toIEW->doneSeqNum = inst->seqNum; lastCommitCycle = curTick; @@ -1357,7 +1371,8 @@ LWBackEnd<Impl>::squash(const InstSeqNum &sn) } while (memBarrier && memBarrier->seqNum > sn) { - DPRINTF(BE, "[sn:%lli] Memory barrier squashed (or previously squashed)\n", memBarrier->seqNum); + DPRINTF(BE, "[sn:%lli] Memory barrier squashed (or previously " + "squashed)\n", memBarrier->seqNum); memBarrier->clearMemDependents(); if (memBarrier->memDepReady()) { DPRINTF(BE, "No previous barrier\n"); diff --git a/cpu/ozone/lw_lsq.hh b/cpu/ozone/lw_lsq.hh index 042610324..6fe343b42 100644 --- a/cpu/ozone/lw_lsq.hh +++ b/cpu/ozone/lw_lsq.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -138,7 +138,6 @@ class OzoneLWLSQ { /** Executes a load instruction. */ Fault executeLoad(DynInstPtr &inst); -// Fault executeLoad(int lq_idx); /** Executes a store instruction. */ Fault executeStore(DynInstPtr &inst); @@ -304,10 +303,8 @@ class OzoneLWLSQ { Status _status; /** The store queue. */ -// std::vector<SQEntry> storeQueue; std::list<SQEntry> storeQueue; /** The load queue. */ -// std::vector<DynInstPtr> loadQueue; std::list<DynInstPtr> loadQueue; typedef typename std::list<SQEntry>::iterator SQIt; @@ -365,7 +362,6 @@ class OzoneLWLSQ { */ InstSeqNum stallingStoreIsn; /** The index of the above store. */ -// int stallingLoadIdx; LQIt stallingLoad; /** Whether or not a load is blocked due to the memory system. It is @@ -398,8 +394,6 @@ class OzoneLWLSQ { template <class T> Fault write(MemReqPtr &req, T &data, int store_idx); - /** Returns the index of the head load instruction. */ -// int getLoadHead() { return loadHead; } /** Returns the sequence number of the head load instruction. */ InstSeqNum getLoadHeadSeqNum() { @@ -411,8 +405,6 @@ class OzoneLWLSQ { } - /** Returns the index of the head store instruction. */ -// int getStoreHead() { return storeHead; } /** Returns the sequence number of the head store instruction. */ InstSeqNum getStoreHeadSeqNum() { @@ -604,12 +596,7 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx) DPRINTF(OzoneLSQ, "D-cache: PC:%#x reading from paddr:%#x " "vaddr:%#x flags:%i\n", inst->readPC(), req->paddr, req->vaddr, req->flags); -/* - Addr debug_addr = ULL(0xfffffc0000be81a8); - if (req->vaddr == debug_addr) { - debug_break(); - } -*/ + assert(!req->completionEvent); req->completionEvent = new typename BackEnd::LdWritebackEvent(inst, be); @@ -631,9 +618,6 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx) _status = DcacheMissStall; } else { -// DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n", -// inst->seqNum); - DPRINTF(OzoneLSQ, "D-cache hit!\n"); } } else { @@ -664,12 +648,7 @@ OzoneLWLSQ<Impl>::write(MemReqPtr &req, T &data, int store_idx) assert(!req->data); req->data = new uint8_t[64]; memcpy(req->data, (uint8_t *)&(*sq_it).data, req->size); -/* - Addr debug_addr = ULL(0xfffffc0000be81a8); - if (req->vaddr == debug_addr) { - debug_break(); - } -*/ + // This function only writes the data to the store queue, so no fault // can happen here. return NoFault; diff --git a/cpu/ozone/lw_lsq_impl.hh b/cpu/ozone/lw_lsq_impl.hh index fdf6bff07..2f85a0396 100644 --- a/cpu/ozone/lw_lsq_impl.hh +++ b/cpu/ozone/lw_lsq_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -104,12 +104,6 @@ OzoneLWLSQ<Impl>::init(Params *params, unsigned maxLQEntries, SQIndices.push(i); } - // May want to initialize these entries to NULL - -// loadHead = loadTail = 0; - -// storeHead = storeWBIdx = storeTail = 0; - usedPorts = 0; cachePorts = params->cachePorts; @@ -197,8 +191,6 @@ OzoneLWLSQ<Impl>::insert(DynInstPtr &inst) } else { insertStore(inst); } - -// inst->setInLSQ(); } template <class Impl> @@ -569,12 +561,9 @@ OzoneLWLSQ<Impl>::writebackStores() } if (result != MA_HIT && dcacheInterface->doEvents()) { -// Event *wb = NULL; store_event->miss = true; typename BackEnd::LdWritebackEvent *wb = NULL; if (req->flags & LOCKED) { - // Stx_C does not generate a system port transaction. -// req->result=1; wb = new typename BackEnd::LdWritebackEvent(inst, be); store_event->wbEvent = wb; @@ -585,8 +574,6 @@ OzoneLWLSQ<Impl>::writebackStores() // DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", // inst->seqNum); - // Will stores need their own kind of writeback events? - // Do stores even need writeback events? be->addDcacheMiss(inst); lastDcacheStall = curTick; @@ -604,20 +591,16 @@ OzoneLWLSQ<Impl>::writebackStores() // inst->seqNum); if (req->flags & LOCKED) { - // Stx_C does not generate a system port transaction. -/* if (req->flags & UNCACHEABLE) { - req->result = 2; - } else { - req->result = 1; - } -*/ + // Stx_C does not generate a system port + // transaction in the 21264, but that might be + // hard to accomplish in this model. + typename BackEnd::LdWritebackEvent *wb = new typename BackEnd::LdWritebackEvent(inst, be); store_event->wbEvent = wb; } sq_it--; -// completeStore(inst->sqIdx); } } else { panic("Must HAVE DCACHE!!!!!\n"); @@ -780,7 +763,7 @@ OzoneLWLSQ<Impl>::completeStore(int store_idx) SQIndices.push(inst->sqIdx); storeQueue.erase(sq_it); --stores; -// assert(!inst->isCompleted()); + inst->setCompleted(); if (cpu->checker) { cpu->checker->tick(inst); @@ -791,7 +774,6 @@ template <class Impl> void OzoneLWLSQ<Impl>::switchOut() { -// assert(loads == 0); assert(storesToWB == 0); switchedOut = true; SQIt sq_it = --(storeQueue.end()); @@ -804,8 +786,6 @@ OzoneLWLSQ<Impl>::switchOut() if ((*sq_it).size == 0 && !(*sq_it).completed) { sq_it--; -// completeStore(inst->sqIdx); - continue; } @@ -817,7 +797,8 @@ OzoneLWLSQ<Impl>::switchOut() continue; } else if ((*sq_it).req->flags & LOCKED) { sq_it--; - assert(!(*sq_it).canWB || ((*sq_it).canWB && (*sq_it).req->flags & LOCKED)); + assert(!(*sq_it).canWB || + ((*sq_it).canWB && (*sq_it).req->flags & LOCKED)); continue; } @@ -886,12 +867,6 @@ OzoneLWLSQ<Impl>::takeOverFrom(ExecContext *old_xc) SQIndices.push(i); } - // May want to initialize these entries to NULL - -// loadHead = loadTail = 0; - -// storeHead = storeWBIdx = storeTail = 0; - usedPorts = 0; loadFaultInst = storeFaultInst = memDepViolator = NULL; diff --git a/cpu/ozone/rename_table.hh b/cpu/ozone/rename_table.hh index afbf6ff32..6ee23b21b 100644 --- a/cpu/ozone/rename_table.hh +++ b/cpu/ozone/rename_table.hh @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ + #ifndef __CPU_OZONE_RENAME_TABLE_HH__ #define __CPU_OZONE_RENAME_TABLE_HH__ diff --git a/cpu/ozone/thread_state.hh b/cpu/ozone/thread_state.hh index 269fc6459..c86c3a720 100644 --- a/cpu/ozone/thread_state.hh +++ b/cpu/ozone/thread_state.hh @@ -1,3 +1,30 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ #ifndef __CPU_OZONE_THREAD_STATE_HH__ #define __CPU_OZONE_THREAD_STATE_HH__ @@ -62,19 +89,14 @@ struct OzoneThreadState : public ThreadState { void setStatus(Status new_status) { _status = new_status; } - RenameTable<Impl> renameTable; // Should I include backend and frontend - // tables here? For the ozone CPU, maybe, for the new full CPU, probably - // not...you wouldn't want threads just accessing the backend/frontend - // rename tables. - Addr PC; // What should these be set to? Probably the committed ones. + RenameTable<Impl> renameTable; + Addr PC; Addr nextPC; - // Current instruction? + // Current instruction TheISA::MachInst inst; TheISA::RegFile regs; - // Front end? Back end? -// MemReqPtr memReq; typename Impl::FullCPU *cpu; diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 07f9d0dad..c03945ffa 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -782,7 +782,7 @@ SimpleCPU::tick() #if FULL_SYSTEM if (system->kernelBinning->fnbin) { - assert(kernelStats); + assert(cpuXC->getKernelStats()); system->kernelBinning->execute(xcProxy, inst); } diff --git a/cpu/thread_state.hh b/cpu/thread_state.hh index e8381b9d3..e09cb12fd 100644 --- a/cpu/thread_state.hh +++ b/cpu/thread_state.hh @@ -1,3 +1,30 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ #ifndef __CPU_THREAD_STATE_HH__ #define __CPU_THREAD_STATE_HH__ @@ -8,11 +35,20 @@ class EndQuiesceEvent; class FunctionProfile; class ProfileNode; +namespace Kernel { + class Statistics; +}; #else -class Process; class FunctionalMemory; +class Process; #endif +/** + * Struct for holding general thread state that is needed across CPU + * models. This includes things such as pointers to the process, + * memory, quiesce events, and certain stats. This can be expanded + * to hold more thread-specific stats within it. + */ struct ThreadState { #if FULL_SYSTEM ThreadState(int _cpuId, int _tid, FunctionalMemory *_mem) @@ -55,6 +91,7 @@ struct ThreadState { EndQuiesceEvent *quiesceEvent; + Kernel::Statistics *kernelStats; #else Process *process; diff --git a/kern/system_events.cc b/kern/system_events.cc index 9b9861497..221eb228d 100644 --- a/kern/system_events.cc +++ b/kern/system_events.cc @@ -67,15 +67,17 @@ FnEvent::process(ExecContext *xc) void IdleStartEvent::process(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->setIdleProcess( - xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc); + if (xc->getKernelStats()) + xc->getKernelStats()->setIdleProcess( + xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc); remove(); } void InterruptStartEvent::process(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->mode(Kernel::interrupt, xc); + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::interrupt, xc); } void @@ -83,5 +85,6 @@ InterruptEndEvent::process(ExecContext *xc) { // We go back to kernel, if we are user, inside the rti // pal code we will get switched to user because of the ICM write - xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc); + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::kernel, xc); } diff --git a/sim/pseudo_inst.cc b/sim/pseudo_inst.cc index 4d9541b58..0c20a6a53 100644 --- a/sim/pseudo_inst.cc +++ b/sim/pseudo_inst.cc @@ -65,7 +65,8 @@ namespace AlphaPseudo void arm(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->arm(); + if (xc->getKernelStats()) + xc->getKernelStats()->arm(); } void @@ -75,7 +76,8 @@ namespace AlphaPseudo return; xc->suspend(); - xc->getCpuPtr()->kernelStats->quiesce(); + if (xc->getKernelStats()) + xc->getKernelStats()->arm(); } void @@ -92,7 +94,8 @@ namespace AlphaPseudo quiesceEvent->schedule(curTick + Clock::Int::ns * ns); xc->suspend(); - xc->getCpuPtr()->kernelStats->quiesce(); + if (xc->getKernelStats()) + xc->getKernelStats()->quiesce(); } void @@ -111,7 +114,8 @@ namespace AlphaPseudo xc->getCpuPtr()->cycles(cycles)); xc->suspend(); - xc->getCpuPtr()->kernelStats->quiesce(); + if (xc->getKernelStats()) + xc->getKernelStats()->quiesce(); } uint64_t @@ -123,7 +127,8 @@ namespace AlphaPseudo void ivlb(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->ivlb(); + if (xc->getKernelStats()) + xc->getKernelStats()->ivlb(); } void |