Merge ktlim@zizzer:/bk/m5
into zamp.eecs.umich.edu:/z/ktlim2/clean/m5-o3 --HG-- extra : convert_revision : 0a6140f3f5e7c454981c5aa2b221224f076e50eb
This commit is contained in:
commit
b414c9e736
31 changed files with 551 additions and 782 deletions
|
@ -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:
|
||||
|
|
23
cpu/base.cc
23
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
|
||||
|
|
10
cpu/base.hh
10
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__
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -588,6 +588,16 @@ InstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst)
|
|||
insertNonSpec(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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -782,7 +782,7 @@ SimpleCPU::tick()
|
|||
|
||||
#if FULL_SYSTEM
|
||||
if (system->kernelBinning->fnbin) {
|
||||
assert(kernelStats);
|
||||
assert(cpuXC->getKernelStats());
|
||||
system->kernelBinning->execute(xcProxy, inst);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue