Fixes to get compiling to work. This is mainly fixing up some includes; changing functions within the XCs; changing MemReqPtrs to Requests or Packets where appropriate.

Currently the O3 and Ozone CPUs do not work in the new memory system; I still need to fix up the ports to work and handle responses properly.  This check-in is so that the merge between m5 and newmem is no longer outstanding.

src/SConscript:
    Need to include FU Pool for new CPU model.  I'll try to figure out a cleaner way to handle this in the future.
src/base/traceflags.py:
    Include new traces flags, fix up merge mess up.
src/cpu/SConscript:
    Include the base_dyn_inst.cc as one of othe sources.
    Don't compile the Ozone CPU for now.
src/cpu/base.cc:
    Remove an extra } from the merge.
src/cpu/base_dyn_inst.cc:
    Fixes to make compiling work.  Don't instantiate the OzoneCPU for now.
src/cpu/base_dyn_inst.hh:
src/cpu/o3/2bit_local_pred.cc:
src/cpu/o3/alpha_cpu_builder.cc:
src/cpu/o3/alpha_cpu_impl.hh:
src/cpu/o3/alpha_dyn_inst.hh:
src/cpu/o3/alpha_params.hh:
src/cpu/o3/bpred_unit.cc:
src/cpu/o3/btb.hh:
src/cpu/o3/commit.hh:
src/cpu/o3/commit_impl.hh:
src/cpu/o3/cpu.cc:
src/cpu/o3/cpu.hh:
src/cpu/o3/fetch.hh:
src/cpu/o3/fetch_impl.hh:
src/cpu/o3/free_list.hh:
src/cpu/o3/iew.hh:
src/cpu/o3/iew_impl.hh:
src/cpu/o3/inst_queue.hh:
src/cpu/o3/inst_queue_impl.hh:
src/cpu/o3/regfile.hh:
src/cpu/o3/sat_counter.hh:
src/cpu/op_class.hh:
src/cpu/ozone/cpu.hh:
src/cpu/checker/cpu.cc:
src/cpu/checker/cpu.hh:
src/cpu/checker/exec_context.hh:
src/cpu/checker/o3_cpu_builder.cc:
src/cpu/ozone/cpu_impl.hh:
src/mem/request.hh:
src/cpu/o3/fu_pool.hh:
src/cpu/o3/lsq.hh:
src/cpu/o3/lsq_unit.hh:
src/cpu/o3/lsq_unit_impl.hh:
src/cpu/o3/thread_state.hh:
src/cpu/ozone/back_end.hh:
src/cpu/ozone/dyn_inst.cc:
src/cpu/ozone/dyn_inst.hh:
src/cpu/ozone/front_end.hh:
src/cpu/ozone/inorder_back_end.hh:
src/cpu/ozone/lw_back_end.hh:
src/cpu/ozone/lw_lsq.hh:
src/cpu/ozone/ozone_impl.hh:
src/cpu/ozone/thread_state.hh:
    Fixes to get compiling to work.
src/cpu/o3/alpha_cpu.hh:
    Fixes to get compiling to work.
    Float reg accessors have changed, as well as MemReqPtrs to RequestPtrs.
src/cpu/o3/alpha_dyn_inst_impl.hh:
    Fixes to get compiling to work.
    Pass in the packet to the completeAcc function.
    Fix up syscall function.

--HG--
rename : cpu/activity.cc => src/cpu/activity.cc
rename : cpu/activity.hh => src/cpu/activity.hh
rename : cpu/checker/cpu.cc => src/cpu/checker/cpu.cc
rename : cpu/checker/cpu.hh => src/cpu/checker/cpu.hh
rename : cpu/checker/cpu_builder.cc => src/cpu/checker/cpu_builder.cc
rename : cpu/checker/exec_context.hh => src/cpu/checker/exec_context.hh
rename : cpu/checker/o3_cpu_builder.cc => src/cpu/checker/o3_cpu_builder.cc
rename : cpu/o3/dep_graph.hh => src/cpu/o3/dep_graph.hh
rename : cpu/o3/fu_pool.cc => src/cpu/o3/fu_pool.cc
rename : cpu/o3/fu_pool.hh => src/cpu/o3/fu_pool.hh
rename : cpu/o3/lsq.cc => src/cpu/o3/lsq.cc
rename : cpu/o3/lsq.hh => src/cpu/o3/lsq.hh
rename : cpu/o3/lsq_impl.hh => src/cpu/o3/lsq_impl.hh
rename : cpu/o3/lsq_unit.cc => src/cpu/o3/lsq_unit.cc
rename : cpu/o3/lsq_unit.hh => src/cpu/o3/lsq_unit.hh
rename : cpu/o3/lsq_unit_impl.hh => src/cpu/o3/lsq_unit_impl.hh
rename : cpu/o3/scoreboard.cc => src/cpu/o3/scoreboard.cc
rename : cpu/o3/scoreboard.hh => src/cpu/o3/scoreboard.hh
rename : cpu/o3/thread_state.hh => src/cpu/o3/thread_state.hh
rename : cpu/ozone/back_end.cc => src/cpu/ozone/back_end.cc
rename : cpu/ozone/back_end.hh => src/cpu/ozone/back_end.hh
rename : cpu/ozone/back_end_impl.hh => src/cpu/ozone/back_end_impl.hh
rename : cpu/ozone/cpu_builder.cc => src/cpu/ozone/cpu_builder.cc
rename : cpu/ozone/dyn_inst.cc => src/cpu/ozone/dyn_inst.cc
rename : cpu/ozone/dyn_inst.hh => src/cpu/ozone/dyn_inst.hh
rename : cpu/ozone/dyn_inst_impl.hh => src/cpu/ozone/dyn_inst_impl.hh
rename : cpu/ozone/front_end.cc => src/cpu/ozone/front_end.cc
rename : cpu/ozone/front_end.hh => src/cpu/ozone/front_end.hh
rename : cpu/ozone/front_end_impl.hh => src/cpu/ozone/front_end_impl.hh
rename : cpu/ozone/inorder_back_end.cc => src/cpu/ozone/inorder_back_end.cc
rename : cpu/ozone/inorder_back_end.hh => src/cpu/ozone/inorder_back_end.hh
rename : cpu/ozone/inorder_back_end_impl.hh => src/cpu/ozone/inorder_back_end_impl.hh
rename : cpu/ozone/inst_queue.cc => src/cpu/ozone/inst_queue.cc
rename : cpu/ozone/inst_queue.hh => src/cpu/ozone/inst_queue.hh
rename : cpu/ozone/inst_queue_impl.hh => src/cpu/ozone/inst_queue_impl.hh
rename : cpu/ozone/lsq_unit.cc => src/cpu/ozone/lsq_unit.cc
rename : cpu/ozone/lsq_unit.hh => src/cpu/ozone/lsq_unit.hh
rename : cpu/ozone/lsq_unit_impl.hh => src/cpu/ozone/lsq_unit_impl.hh
rename : cpu/ozone/lw_back_end.cc => src/cpu/ozone/lw_back_end.cc
rename : cpu/ozone/lw_back_end.hh => src/cpu/ozone/lw_back_end.hh
rename : cpu/ozone/lw_back_end_impl.hh => src/cpu/ozone/lw_back_end_impl.hh
rename : cpu/ozone/lw_lsq.cc => src/cpu/ozone/lw_lsq.cc
rename : cpu/ozone/lw_lsq.hh => src/cpu/ozone/lw_lsq.hh
rename : cpu/ozone/lw_lsq_impl.hh => src/cpu/ozone/lw_lsq_impl.hh
rename : cpu/ozone/null_predictor.hh => src/cpu/ozone/null_predictor.hh
rename : cpu/ozone/ozone_impl.hh => src/cpu/ozone/ozone_impl.hh
rename : cpu/ozone/rename_table.cc => src/cpu/ozone/rename_table.cc
rename : cpu/ozone/rename_table.hh => src/cpu/ozone/rename_table.hh
rename : cpu/ozone/rename_table_impl.hh => src/cpu/ozone/rename_table_impl.hh
rename : cpu/ozone/simple_impl.hh => src/cpu/ozone/simple_impl.hh
rename : cpu/ozone/simple_params.hh => src/cpu/ozone/simple_params.hh
rename : cpu/ozone/thread_state.hh => src/cpu/ozone/thread_state.hh
rename : cpu/quiesce_event.cc => src/cpu/quiesce_event.cc
rename : cpu/quiesce_event.hh => src/cpu/quiesce_event.hh
rename : cpu/thread_state.hh => src/cpu/thread_state.hh
rename : python/m5/objects/FUPool.py => src/python/m5/objects/FUPool.py
rename : python/m5/objects/OzoneCPU.py => src/python/m5/objects/OzoneCPU.py
rename : python/m5/objects/SimpleOzoneCPU.py => src/python/m5/objects/SimpleOzoneCPU.py
extra : convert_revision : ca7f0fbf65ee1a70d482fb4eda9a1840c7f9b8f8
This commit is contained in:
Kevin Lim 2006-06-02 18:15:20 -04:00
parent d4b73086b6
commit 7940c10ace
90 changed files with 1007 additions and 891 deletions

View file

@ -89,7 +89,9 @@ base_sources = Split('''
cpu/quiesce_event.cc
cpu/static_inst.cc
cpu/sampler/sampler.cc
encumbered/cpu/full/fu_pool.cc
mem/bridge.cc
mem/bus.cc
mem/connector.cc

View file

@ -53,6 +53,7 @@ baseFlags = [
'BusBridge',
'Cache',
'Chains',
'Checker',
'Clock',
'Commit',
'CommitRate',
@ -116,6 +117,44 @@ baseFlags = [
'IBE',
'BE',
'OzoneLSQ',
'PCEvent',
'PCIA',
'PCIDEV',
'PciConfigAll',
'Pipeline',
'Printf',
'ROB',
'Regs',
'Rename',
'RenameMap',
'SQL',
'Sampler',
'ScsiCtrl',
'ScsiDisk',
'ScsiNone',
'Serialize',
'SimpleCPU',
'SimpleDisk',
'SimpleDiskData',
'Sparc',
'Split',
'Stack',
'StatEvents',
'Stats',
'StoreSet',
'Syscall',
'SyscallVerbose',
'TCPIP',
'TLB',
'Thread',
'Timer',
'Tsunami',
'Uart',
'VtoPhys',
'WriteBarrier',
'Activity',
'Scoreboard',
'Writeback',
]
#

View file

@ -116,6 +116,7 @@ if 'FastCPU' in env['CPU_MODELS']:
if 'AlphaFullCPU' in env['CPU_MODELS']:
sources += Split('''
base_dyn_inst.cc
o3/2bit_local_pred.cc
o3/alpha_dyn_inst.cc
o3/alpha_cpu.cc
@ -155,7 +156,6 @@ if 'OzoneSimpleCPU' in env['CPU_MODELS']:
if 'OzoneCPU' in env['CPU_MODELS']:
sources += Split('''
ozone/back_end.cc
ozone/lsq_unit.cc
ozone/lw_back_end.cc
ozone/lw_lsq.cc
@ -164,7 +164,6 @@ if 'OzoneCPU' in env['CPU_MODELS']:
if 'CheckerCPU' in env['CPU_MODELS']:
sources += Split('''
checker/cpu.cc
checker/cpu_builder.cc
checker/o3_cpu_builder.cc
''')

View file

@ -229,7 +229,6 @@ BaseCPU::registerExecContexts()
#else
xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc));
#endif
}
}
}

View file

@ -36,13 +36,13 @@
#include "arch/faults.hh"
#include "cpu/exetrace.hh"
#include "mem/mem_req.hh"
#include "mem/request.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/ozone/simple_impl.hh"
#include "cpu/ozone/ozone_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
//#include "cpu/ozone/ozone_impl.hh"
using namespace std;
using namespace TheISA;
@ -94,8 +94,8 @@ void
BaseDynInst<Impl>::initVars()
{
req = NULL;
effAddr = MemReq::inval_addr;
physEffAddr = MemReq::inval_addr;
effAddr = 0;
physEffAddr = 0;
storeSize = 0;
readyRegs = 0;
@ -198,7 +198,7 @@ BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags)
// This is the "functional" implementation of prefetch. Not much
// happens here since prefetches don't affect the architectural
// state.
/*
// Generate a MemReq so we can translate the effective address.
MemReqPtr req = new MemReq(addr, thread->getXCProxy(), 1, flags);
req->asid = asid;
@ -226,6 +226,7 @@ BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags)
if (traceData) {
traceData->setAddr(addr);
}
*/
}
template <class Impl>
@ -236,6 +237,7 @@ BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
// will casue a TLB miss trap if necessary... not sure whether
// that's the best thing to do or not. We don't really need the
// MemReq otherwise, since wh64 has no functional effect.
/*
MemReqPtr req = new MemReq(addr, thread->getXCProxy(), size, flags);
req->asid = asid;
@ -255,6 +257,7 @@ BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
storeSize = size;
storeData = 0;
*/
}
/**
@ -264,6 +267,7 @@ template <class Impl>
Fault
BaseDynInst<Impl>::copySrcTranslate(Addr src)
{
/*
MemReqPtr req = new MemReq(src, thread->getXCProxy(), 64);
req->asid = asid;
@ -278,6 +282,8 @@ BaseDynInst<Impl>::copySrcTranslate(Addr src)
thread->copySrcPhysAddr = 0;
}
return fault;
*/
return NoFault;
}
/**
@ -287,6 +293,7 @@ template <class Impl>
Fault
BaseDynInst<Impl>::copy(Addr dest)
{
/*
uint8_t data[64];
FunctionalMemory *mem = thread->mem;
assert(thread->copySrcPhysAddr || thread->misspeculating());
@ -305,6 +312,8 @@ BaseDynInst<Impl>::copy(Addr dest)
mem->write(req, data);
}
return fault;
*/
return NoFault;
}
template <class Impl>
@ -432,7 +441,7 @@ template class BaseDynInst<AlphaSimpleImpl>;
template <>
int
BaseDynInst<AlphaSimpleImpl>::instcount = 0;
/*
// Forward declaration
template class BaseDynInst<SimpleImpl>;
@ -446,3 +455,4 @@ template class BaseDynInst<OzoneImpl>;
template <>
int
BaseDynInst<OzoneImpl>::instcount = 0;
*/

View file

@ -32,14 +32,15 @@
#include <list>
#include <string>
#include "arch/faults.hh"
#include "base/fast_alloc.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/exetrace.hh"
#include "cpu/inst_seq.hh"
#include "cpu/op_class.hh"
#include "cpu/static_inst.hh"
#include "encumbered/cpu/full/op_class.hh"
#include "mem/functional/memory_control.hh"
#include "mem/packet.hh"
#include "sim/system.hh"
/*
#include "encumbered/cpu/full/bpred_update.hh"
@ -197,7 +198,11 @@ class BaseDynInst : public FastAlloc, public RefCounted
Fault fault;
/** The memory request. */
MemReqPtr req;
// MemReqPtr req;
Request *req;
// Packet pkt;
uint8_t *memData;
/** The effective virtual address (lds & stores only). */
Addr effAddr;
@ -287,12 +292,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
* @param p Memory accessed.
* @param nbytes Access size.
*/
void
trace_mem(Fault fault,
MemCmd cmd,
Addr addr,
void *p,
int nbytes);
// void
// trace_mem(Fault fault,
// MemCmd cmd,
// Addr addr,
// void *p,
// int nbytes);
/** Dumps out contents of this BaseDynInst. */
void dump();
@ -601,7 +606,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
/** Returns the effective address. */
const Addr &getEA() const { return req->vaddr; }
const Addr &getEA() const { return instEffAddr; }
/** Returns whether or not the eff. addr. calculation has been completed. */
bool doneEACalc() { return eaCalcDone; }
@ -637,25 +642,25 @@ inline Fault
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
{
if (executed) {
panic("Not supposed to re-execute with split mem ops!");
fault = cpu->read(req, data, lqIdx);
return fault;
}
req = new MemReq(addr, thread->getXCProxy(), sizeof(T), flags);
req->asid = asid;
req->thread_num = threadNumber;
req->pc = this->PC;
req = new Request();
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
req->setThreadContext(thread->cpuId, threadNumber);
if ((req->vaddr & (TheISA::VMPageSize - 1)) + req->size >
if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
TheISA::VMPageSize) {
return TheISA::genAlignmentFault();
}
fault = cpu->translateDataReadReq(req);
effAddr = req->vaddr;
physEffAddr = req->paddr;
memReqFlags = req->flags;
effAddr = req->getVaddr();
physEffAddr = req->getPaddr();
memReqFlags = req->getFlags();
if (fault == NoFault) {
#if FULL_SYSTEM
@ -697,22 +702,20 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
traceData->setData(data);
}
req = new MemReq(addr, thread->getXCProxy(), sizeof(T), flags);
req = new Request();
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
req->setThreadContext(thread->cpuId, threadNumber);
req->asid = asid;
req->thread_num = threadNumber;
req->pc = this->PC;
if ((req->vaddr & (TheISA::VMPageSize - 1)) + req->size >
if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
TheISA::VMPageSize) {
return TheISA::genAlignmentFault();
}
fault = cpu->translateDataWriteReq(req);
effAddr = req->vaddr;
physEffAddr = req->paddr;
memReqFlags = req->flags;
effAddr = req->getVaddr();
physEffAddr = req->getPaddr();
memReqFlags = req->getFlags();
if (fault == NoFault) {
#if FULL_SYSTEM
@ -729,7 +732,7 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
if (res) {
// always return some result to keep misspeculated paths
// (which will ignore faults) deterministic
*res = (fault == NoFault) ? req->result : 0;
*res = (fault == NoFault) ? req->getScResult() : 0;
}
return fault;

View file

@ -43,9 +43,9 @@
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/ozone/dyn_inst.hh"
#include "cpu/ozone/ozone_impl.hh"
#include "cpu/ozone/simple_impl.hh"
//#include "cpu/ozone/dyn_inst.hh"
//#include "cpu/ozone/ozone_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
#if FULL_SYSTEM
#include "sim/system.hh"
@ -64,10 +64,8 @@ CheckerCPU::init()
CheckerCPU::CheckerCPU(Params *p)
: BaseCPU(p), cpuXC(NULL), xcProxy(NULL)
{
memReq = new MemReq();
memReq->xc = xcProxy;
memReq->asid = 0;
memReq->data = new uint8_t[64];
memReq = new Request();
// memReq->data = new uint8_t[64];
numInst = 0;
startNumInst = 0;
@ -91,12 +89,12 @@ CheckerCPU::~CheckerCPU()
}
void
CheckerCPU::setMemory(FunctionalMemory *mem)
CheckerCPU::setMemory(MemObject *mem)
{
memPtr = mem;
#if !FULL_SYSTEM
cpuXC = new CPUExecContext(this, /* thread_num */ 0, mem,
/* asid */ 0);
cpuXC = new CPUExecContext(this, /* thread_num */ 0, NULL,
/* asid */ 0, mem);
cpuXC->setStatus(ExecContext::Suspended);
xcProxy = cpuXC->getProxy();
@ -172,6 +170,7 @@ template <class T>
Fault
CheckerCPU::read(Addr addr, T &data, unsigned flags)
{
/*
memReq->reset(addr, sizeof(T), flags);
// translate to physical address
@ -189,7 +188,7 @@ CheckerCPU::read(Addr addr, T &data, unsigned flags)
// Assume the data is correct if it's an uncached access
memcpy(&data, &unverifiedResult.integer, sizeof(T));
}
*/
return NoFault;
}
@ -238,6 +237,7 @@ template <class T>
Fault
CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
/*
memReq->reset(addr, sizeof(T), flags);
// translate to physical address
@ -280,7 +280,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
// value.
if (res)
*res = unverifiedReq->result;
*/
return NoFault;
}
@ -335,7 +335,7 @@ CheckerCPU::dbg_vtophys(Addr addr)
#endif // FULL_SYSTEM
bool
CheckerCPU::translateInstReq(MemReqPtr &req)
CheckerCPU::translateInstReq(Request *req)
{
#if FULL_SYSTEM
return (cpuXC->translateInstReq(req) == NoFault);
@ -346,53 +346,53 @@ CheckerCPU::translateInstReq(MemReqPtr &req)
}
void
CheckerCPU::translateDataReadReq(MemReqPtr &req)
CheckerCPU::translateDataReadReq(Request *req)
{
cpuXC->translateDataReadReq(req);
if (req->vaddr != unverifiedReq->vaddr) {
if (req->getVaddr() != unverifiedReq->getVaddr()) {
warn("%lli: Request virtual addresses do not match! Inst: %#x, "
"checker: %#x",
curTick, unverifiedReq->vaddr, req->vaddr);
curTick, unverifiedReq->getVaddr(), req->getVaddr());
handleError();
}
req->paddr = unverifiedReq->paddr;
req->setPaddr(unverifiedReq->getPaddr());
if (checkFlags(req)) {
warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
curTick, unverifiedReq->flags, req->flags);
curTick, unverifiedReq->getFlags(), req->getFlags());
handleError();
}
}
void
CheckerCPU::translateDataWriteReq(MemReqPtr &req)
CheckerCPU::translateDataWriteReq(Request *req)
{
cpuXC->translateDataWriteReq(req);
if (req->vaddr != unverifiedReq->vaddr) {
if (req->getVaddr() != unverifiedReq->getVaddr()) {
warn("%lli: Request virtual addresses do not match! Inst: %#x, "
"checker: %#x",
curTick, unverifiedReq->vaddr, req->vaddr);
curTick, unverifiedReq->getVaddr(), req->getVaddr());
handleError();
}
req->paddr = unverifiedReq->paddr;
req->setPaddr(unverifiedReq->getPaddr());
if (checkFlags(req)) {
warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
curTick, unverifiedReq->flags, req->flags);
curTick, unverifiedReq->getFlags(), req->getFlags());
handleError();
}
}
bool
CheckerCPU::checkFlags(MemReqPtr &req)
CheckerCPU::checkFlags(Request *req)
{
// Remove any dynamic flags that don't have to do with the request itself.
unsigned flags = unverifiedReq->flags;
unsigned flags = unverifiedReq->getFlags();
unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
flags = flags & (mask);
if (flags == req->flags) {
if (flags == req->getFlags()) {
return false;
} else {
return true;
@ -495,9 +495,9 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
#endif
// set up memory request for instruction fetch
memReq->cmd = Read;
memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
IFETCH_FLAGS(cpuXC->readPC()));
// memReq->cmd = Read;
// memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
// IFETCH_FLAGS(cpuXC->readPC()));
bool succeeded = translateInstReq(memReq);
@ -526,7 +526,7 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
}
if (fault == NoFault) {
cpuXC->mem->read(memReq, machInst);
// cpuXC->read(memReq, machInst);
// keep an instruction count
numInst++;
@ -674,7 +674,7 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
if (idx < TheISA::FP_Base_DepTag) {
cpuXC->setIntReg(idx, inst->readIntResult());
} else if (idx < TheISA::Fpcr_DepTag) {
cpuXC->setFloatRegInt(idx, inst->readIntResult());
cpuXC->setFloatRegBits(idx, inst->readIntResult());
} else {
cpuXC->setMiscReg(idx, inst->readIntResult());
}
@ -750,8 +750,8 @@ Checker<DynInstPtr>::dumpInsts()
}
template
class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
//template
//class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
template
class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;

View file

@ -33,6 +33,7 @@
#include <queue>
#include <map>
#include "arch/types.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
@ -62,12 +63,15 @@ class BaseDynInst;
class ExecContext;
class MemInterface;
class Checkpoint;
class Request;
class Sampler;
class CheckerCPU : public BaseCPU
{
protected:
typedef TheISA::MachInst MachInst;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
public:
// main simulation loop (one cycle)
@ -89,9 +93,9 @@ class CheckerCPU : public BaseCPU
CheckerCPU(Params *p);
virtual ~CheckerCPU();
void setMemory(FunctionalMemory *mem);
void setMemory(MemObject *mem);
FunctionalMemory *memPtr;
MemObject *memPtr;
#if FULL_SYSTEM
void setSystem(System *system);
@ -123,7 +127,7 @@ class CheckerCPU : public BaseCPU
MachInst machInst;
// Refcounted pointer to the one memory request.
MemReqPtr memReq;
Request *memReq;
StaticInstPtr curStaticInst;
@ -186,22 +190,28 @@ class CheckerCPU : public BaseCPU
return cpuXC->readIntReg(si->srcRegIdx(idx));
}
float readFloatRegSingle(const StaticInst *si, int idx)
FloatReg readFloatReg(const StaticInst *si, int idx, int width)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return cpuXC->readFloatRegSingle(reg_idx);
return cpuXC->readFloatReg(reg_idx, width);
}
double readFloatRegDouble(const StaticInst *si, int idx)
FloatReg readFloatReg(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return cpuXC->readFloatRegDouble(reg_idx);
return cpuXC->readFloatReg(reg_idx);
}
uint64_t readFloatRegInt(const StaticInst *si, int idx)
FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return cpuXC->readFloatRegInt(reg_idx);
return cpuXC->readFloatRegBits(reg_idx, width);
}
FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return cpuXC->readFloatRegBits(reg_idx);
}
void setIntReg(const StaticInst *si, int idx, uint64_t val)
@ -210,28 +220,46 @@ class CheckerCPU : public BaseCPU
result.integer = val;
}
void setFloatRegSingle(const StaticInst *si, int idx, float val)
void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
cpuXC->setFloatRegSingle(reg_idx, val);
cpuXC->setFloatReg(reg_idx, val, width);
switch(width) {
case 32:
result.fp = val;
break;
case 64:
result.dbl = val;
break;
};
}
void setFloatReg(const StaticInst *si, int idx, FloatReg val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
cpuXC->setFloatReg(reg_idx, val);
result.fp = val;
}
void setFloatRegDouble(const StaticInst *si, int idx, double val)
void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val,
int width)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
cpuXC->setFloatRegDouble(reg_idx, val);
result.dbl = val;
cpuXC->setFloatRegBits(reg_idx, val, width);
result.integer = val;
}
void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
cpuXC->setFloatRegInt(reg_idx, val);
cpuXC->setFloatRegBits(reg_idx, val);
result.integer = val;
}
uint64_t readPC() { return cpuXC->readPC(); }
uint64_t readNextPC() { return cpuXC->readNextPC(); }
void setNextPC(uint64_t val) {
cpuXC->setNextPC(val);
}
@ -262,9 +290,9 @@ class CheckerCPU : public BaseCPU
void recordPCChange(uint64_t val) { changedPC = true; }
void recordNextPCChange(uint64_t val) { changedNextPC = true; }
bool translateInstReq(MemReqPtr &req);
void translateDataWriteReq(MemReqPtr &req);
void translateDataReadReq(MemReqPtr &req);
bool translateInstReq(Request *req);
void translateDataWriteReq(Request *req);
void translateDataReadReq(Request *req);
#if FULL_SYSTEM
Fault hwrei() { return cpuXC->hwrei(); }
@ -276,7 +304,7 @@ class CheckerCPU : public BaseCPU
#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() { }
void syscall(uint64_t callnum) { }
#endif
void handleError()
@ -284,13 +312,13 @@ class CheckerCPU : public BaseCPU
if (exitOnError)
panic("Checker found error!");
}
bool checkFlags(MemReqPtr &req);
bool checkFlags(Request *req);
ExecContext *xcBase() { return xcProxy; }
CPUExecContext *cpuXCBase() { return cpuXC; }
Result unverifiedResult;
MemReqPtr unverifiedReq;
Request *unverifiedReq;
bool changedPC;
bool willChangePC;

View file

@ -65,7 +65,7 @@ class CheckerExecContext : public ExecContext
int readCpuId() { return actualXC->readCpuId(); }
FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); }
TranslatingPort *getMemPort() { return actualXC->getMemPort(); }
#if FULL_SYSTEM
System *getSystemPtr() { return actualXC->getSystemPtr(); }
@ -152,14 +152,17 @@ class CheckerExecContext : public ExecContext
uint64_t readIntReg(int reg_idx)
{ return actualXC->readIntReg(reg_idx); }
float readFloatRegSingle(int reg_idx)
{ return actualXC->readFloatRegSingle(reg_idx); }
FloatReg readFloatReg(int reg_idx, int width)
{ return actualXC->readFloatReg(reg_idx, width); }
double readFloatRegDouble(int reg_idx)
{ return actualXC->readFloatRegDouble(reg_idx); }
FloatReg readFloatReg(int reg_idx)
{ return actualXC->readFloatReg(reg_idx); }
uint64_t readFloatRegInt(int reg_idx)
{ return actualXC->readFloatRegInt(reg_idx); }
FloatRegBits readFloatRegBits(int reg_idx, int width)
{ return actualXC->readFloatRegBits(reg_idx, width); }
FloatRegBits readFloatRegBits(int reg_idx)
{ return actualXC->readFloatRegBits(reg_idx); }
void setIntReg(int reg_idx, uint64_t val)
{
@ -167,22 +170,28 @@ class CheckerExecContext : public ExecContext
checkerXC->setIntReg(reg_idx, val);
}
void setFloatRegSingle(int reg_idx, float val)
void setFloatReg(int reg_idx, FloatReg val, int width)
{
actualXC->setFloatRegSingle(reg_idx, val);
checkerXC->setFloatRegSingle(reg_idx, val);
actualXC->setFloatReg(reg_idx, val, width);
checkerXC->setFloatReg(reg_idx, val, width);
}
void setFloatRegDouble(int reg_idx, double val)
void setFloatReg(int reg_idx, FloatReg val)
{
actualXC->setFloatRegDouble(reg_idx, val);
checkerXC->setFloatRegSingle(reg_idx, val);
actualXC->setFloatReg(reg_idx, val);
checkerXC->setFloatReg(reg_idx, val);
}
void setFloatRegInt(int reg_idx, uint64_t val)
void setFloatRegBits(int reg_idx, FloatRegBits val, int width)
{
actualXC->setFloatRegInt(reg_idx, val);
checkerXC->setFloatRegInt(reg_idx, val);
actualXC->setFloatRegBits(reg_idx, val, width);
checkerXC->setFloatRegBits(reg_idx, val, width);
}
void setFloatRegBits(int reg_idx, FloatRegBits val)
{
actualXC->setFloatRegBits(reg_idx, val);
checkerXC->setFloatRegBits(reg_idx, val);
}
uint64_t readPC() { return actualXC->readPC(); }
@ -203,6 +212,15 @@ class CheckerExecContext : public ExecContext
checkerCPU->recordNextPCChange(val);
}
uint64_t readNextNPC() { return actualXC->readNextNPC(); }
void setNextNPC(uint64_t val)
{
actualXC->setNextNPC(val);
checkerXC->setNextNPC(val);
checkerCPU->recordNextPCChange(val);
}
MiscReg readMiscReg(int misc_reg)
{ return actualXC->readMiscReg(misc_reg); }
@ -254,6 +272,12 @@ class CheckerExecContext : public ExecContext
Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
#endif
void changeRegFileContext(RegFile::ContextParam param,
RegFile::ContextVal val)
{
actualXC->changeRegFileContext(param, val);
checkerXC->changeRegFileContext(param, val);
}
};
#endif // __CPU_CHECKER_EXEC_CONTEXT_HH__

View file

@ -5,11 +5,12 @@
#include "cpu/inst_seq.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "mem/base_mem.hh"
#include "sim/builder.hh"
#include "sim/process.hh"
#include "sim/sim_object.hh"
class MemObject;
class O3Checker : public Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >
{
public:
@ -32,7 +33,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
SimObjectParam<FunctionalMemory *> mem;
SimObjectParam<MemObject *> mem;
SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
@ -40,8 +41,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
SimObjectParam<Process *> workload;
#endif // FULL_SYSTEM
Param<int> clock;
SimObjectParam<BaseMem *> icache;
SimObjectParam<BaseMem *> dcache;
Param<bool> defer_registration;
Param<bool> exitOnError;
@ -73,8 +72,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker)
#endif // FULL_SYSTEM
INIT_PARAM(clock, "clock speed"),
INIT_PARAM(icache, "L1 instruction cache object"),
INIT_PARAM(dcache, "L1 data cache object"),
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(exitOnError, "exit on error"),
@ -105,8 +102,6 @@ CREATE_SIM_OBJECT(O3Checker)
temp = max_insts_all_threads;
temp = max_loads_any_thread;
temp = max_loads_all_threads;
BaseMem *cache = icache;
cache = dcache;
#if FULL_SYSTEM
params->itb = itb;

View file

@ -27,6 +27,7 @@
*/
#include "base/intmath.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "cpu/o3/2bit_local_pred.hh"

View file

@ -39,11 +39,15 @@ namespace Kernel {
class Statistics;
};
class TranslatingPort;
template <class Impl>
class AlphaFullCPU : public FullO3CPU<Impl>
{
protected:
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
typedef TheISA::RegFile RegFile;
typedef TheISA::MiscRegFile MiscRegFile;
@ -69,7 +73,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
virtual int readCpuId() { return cpu->cpu_id; }
virtual FunctionalMemory *getMemPtr() { return thread->mem; }
virtual TranslatingPort *getMemPort() { return /*thread->port*/ NULL; }
#if FULL_SYSTEM
virtual System *getSystemPtr() { return cpu->system; }
@ -135,19 +139,23 @@ class AlphaFullCPU : public FullO3CPU<Impl>
virtual uint64_t readIntReg(int reg_idx);
virtual float readFloatRegSingle(int reg_idx);
virtual FloatReg readFloatReg(int reg_idx, int width);
virtual double readFloatRegDouble(int reg_idx);
virtual FloatReg readFloatReg(int reg_idx);
virtual uint64_t readFloatRegInt(int reg_idx);
virtual FloatRegBits readFloatRegBits(int reg_idx, int width);
virtual FloatRegBits readFloatRegBits(int reg_idx);
virtual void setIntReg(int reg_idx, uint64_t val);
virtual void setFloatRegSingle(int reg_idx, float val);
virtual void setFloatReg(int reg_idx, FloatReg val, int width);
virtual void setFloatRegDouble(int reg_idx, double val);
virtual void setFloatReg(int reg_idx, FloatReg val);
virtual void setFloatRegInt(int reg_idx, uint64_t val);
virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
virtual void setFloatRegBits(int reg_idx, FloatRegBits val);
virtual uint64_t readPC()
{ return cpu->readPC(thread->tid); }
@ -159,6 +167,15 @@ class AlphaFullCPU : public FullO3CPU<Impl>
virtual void setNextPC(uint64_t val);
virtual uint64_t readNextNPC()
{
panic("Alpha has no NextNPC!");
return 0;
}
virtual void setNextNPC(uint64_t val)
{ panic("Alpha has no NextNPC!"); }
virtual MiscReg readMiscReg(int misc_reg)
{ return cpu->readMiscReg(misc_reg, thread->tid); }
@ -193,10 +210,14 @@ class AlphaFullCPU : public FullO3CPU<Impl>
virtual void setSyscallReturn(SyscallReturn return_value);
virtual void syscall() { return cpu->syscall(thread->tid); }
virtual void syscall(int64_t callnum)
{ return cpu->syscall(callnum, thread->tid); }
virtual Counter readFuncExeInst() { return thread->funcExeInst; }
#endif
virtual void changeRegFileContext(TheISA::RegFile::ContextParam param,
TheISA::RegFile::ContextVal val)
{ panic("Not supported on Alpha!"); }
};
#if FULL_SYSTEM
@ -211,52 +232,43 @@ class AlphaFullCPU : public FullO3CPU<Impl>
#if FULL_SYSTEM
/** Translates instruction requestion. */
Fault translateInstReq(MemReqPtr &req)
Fault translateInstReq(RequestPtr &req)
{
return itb->translate(req);
}
/** Translates data read request. */
Fault translateDataReadReq(MemReqPtr &req)
Fault translateDataReadReq(RequestPtr &req)
{
return dtb->translate(req, false);
}
/** Translates data write request. */
Fault translateDataWriteReq(MemReqPtr &req)
Fault translateDataWriteReq(RequestPtr &req)
{
return dtb->translate(req, true);
}
#else
Fault dummyTranslation(MemReqPtr &req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
#endif
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
return NoFault;
}
/** Translates instruction requestion in syscall emulation mode. */
Fault translateInstReq(MemReqPtr &req)
Fault translateInstReq(RequestPtr &req)
{
return dummyTranslation(req);
int tid = req->getThreadNum();
return this->thread[tid]->process->pTable->translate(req);
}
/** Translates data read request in syscall emulation mode. */
Fault translateDataReadReq(MemReqPtr &req)
Fault translateDataReadReq(RequestPtr &req)
{
return dummyTranslation(req);
int tid = req->getThreadNum();
return this->thread[tid]->process->pTable->translate(req);
}
/** Translates data write request in syscall emulation mode. */
Fault translateDataWriteReq(MemReqPtr &req)
Fault translateDataWriteReq(RequestPtr &req)
{
return dummyTranslation(req);
int tid = req->getThreadNum();
return this->thread[tid]->process->pTable->translate(req);
}
#endif
@ -298,7 +310,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
/** Executes a syscall.
* @todo: Determine if this needs to be virtual.
*/
void syscall(int thread_num);
void syscall(int64_t callnum, int thread_num);
/** Gets a syscall argument. */
IntReg getSyscallArg(int i, int tid);
@ -311,7 +323,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
/** Read from memory function. */
template <class T>
Fault read(MemReqPtr &req, T &data)
Fault read(RequestPtr &req, T &data)
{
#if 0
#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
@ -338,14 +350,14 @@ class AlphaFullCPU : public FullO3CPU<Impl>
/** CPU read function, forwards read to LSQ. */
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx)
Fault read(RequestPtr &req, T &data, int load_idx)
{
return this->iew.ldstQueue.read(req, data, load_idx);
}
/** Write to memory function. */
template <class T>
Fault write(MemReqPtr &req, T &data)
Fault write(RequestPtr &req, T &data)
{
#if 0
#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
@ -417,7 +429,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
/** CPU write function, forwards write to LSQ. */
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx)
Fault write(RequestPtr &req, T &data, int store_idx)
{
return this->iew.ldstQueue.write(req, data, store_idx);
}

View file

@ -33,7 +33,6 @@
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_params.hh"
#include "cpu/o3/fu_pool.hh"
#include "mem/cache/base_cache.hh"
#include "sim/builder.hh"
class DerivAlphaFullCPU : public AlphaFullCPU<AlphaSimpleImpl>
@ -60,7 +59,7 @@ SimObjectVectorParam<Process *> workload;
//SimObjectParam<PageTable *> page_table;
#endif // FULL_SYSTEM
SimObjectParam<FunctionalMemory *> mem;
SimObjectParam<MemObject *> mem;
SimObjectParam<BaseCPU *> checker;
@ -69,9 +68,6 @@ Param<Counter> max_insts_all_threads;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
SimObjectParam<BaseCache *> icache;
SimObjectParam<BaseCache *> dcache;
Param<unsigned> cachePorts;
Param<unsigned> decodeToFetchDelay;
@ -169,7 +165,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
// INIT_PARAM(page_table, "Page table"),
#endif // FULL_SYSTEM
INIT_PARAM_DFLT(mem, "Memory", NULL),
INIT_PARAM(mem, "Memory"),
INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
@ -188,9 +184,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
"count",
0),
INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
@ -327,8 +320,6 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
//
// Caches
//
params->icacheInterface = icache ? icache->getInterface() : NULL;
params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
params->cachePorts = cachePorts;
params->decodeToFetchDelay = decodeToFetchDelay;

View file

@ -31,7 +31,6 @@
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/checker/exec_context.hh"
#include "mem/mem_interface.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
@ -68,11 +67,9 @@ AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
this->thread[i]->setStatus(ExecContext::Suspended);
#else
if (i < params->workload.size()) {
DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
"process is %#x",
i, params->workload[i]->prog_entry, this->thread[i]);
DPRINTF(FullCPU, "FullCPU: Workload[%i] process is %#x",
i, this->thread[i]);
this->thread[i] = new Thread(this, i, params->workload[i], i);
assert(params->workload[i]->getMemory() != NULL);
this->thread[i]->setStatus(ExecContext::Suspended);
//usedTids[i] = true;
@ -160,7 +157,7 @@ void
AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context)
{
// some things should already be set up
assert(getMemPtr() == old_context->getMemPtr());
assert(getMemPort() == old_context->getMemPort());
#if FULL_SYSTEM
assert(getSystemPtr() == old_context->getSystemPtr());
#else
@ -366,15 +363,14 @@ AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc)
}
// Then loop through the floating point registers.
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
this->cpuXC->setFloatRegBits(i,
this->regFile.readFloatRegBits(renamed_reg));
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
cpu->setFloatRegBits(renamed_reg,
xc->readFloatRegBits(i));
}
// Copy the misc regs.
cpu->regFile.miscRegs[tid].copyMiscRegs(xc);
copyMiscRegs(xc, this);
// Then finally set the PC and the next PC.
cpu->setPC(xc->readPC(), tid);
@ -398,24 +394,40 @@ AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx)
}
template <class Impl>
float
AlphaFullCPU<Impl>::AlphaXC::readFloatRegSingle(int reg_idx)
FloatReg
AlphaFullCPU<Impl>::AlphaXC::readFloatReg(int reg_idx, int width)
{
DPRINTF(Fault, "Reading float register through the XC!\n");
switch(width) {
case 32:
return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
case 64:
return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
default:
panic("Unsupported width!");
return 0;
}
}
template <class Impl>
FloatReg
AlphaFullCPU<Impl>::AlphaXC::readFloatReg(int reg_idx)
{
DPRINTF(Fault, "Reading float register through the XC!\n");
return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
}
template <class Impl>
double
AlphaFullCPU<Impl>::AlphaXC::readFloatRegDouble(int reg_idx)
FloatRegBits
AlphaFullCPU<Impl>::AlphaXC::readFloatRegBits(int reg_idx, int width)
{
DPRINTF(Fault, "Reading float register through the XC!\n");
return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
DPRINTF(Fault, "Reading floatint register through the XC!\n");
return cpu->readArchFloatRegInt(reg_idx, thread->tid);
}
template <class Impl>
uint64_t
AlphaFullCPU<Impl>::AlphaXC::readFloatRegInt(int reg_idx)
FloatRegBits
AlphaFullCPU<Impl>::AlphaXC::readFloatRegBits(int reg_idx)
{
DPRINTF(Fault, "Reading floatint register through the XC!\n");
return cpu->readArchFloatRegInt(reg_idx, thread->tid);
@ -435,7 +447,26 @@ AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val)
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val)
AlphaFullCPU<Impl>::AlphaXC::setFloatReg(int reg_idx, FloatReg val, int width)
{
DPRINTF(Fault, "Setting float register through the XC!\n");
switch(width) {
case 32:
cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
break;
case 64:
cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
break;
}
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromXC(thread->tid);
}
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaXC::setFloatReg(int reg_idx, FloatReg val)
{
DPRINTF(Fault, "Setting float register through the XC!\n");
cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
@ -447,10 +478,11 @@ AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val)
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val)
AlphaFullCPU<Impl>::AlphaXC::setFloatRegBits(int reg_idx, FloatRegBits val,
int width)
{
DPRINTF(Fault, "Setting float register through the XC!\n");
cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
DPRINTF(Fault, "Setting floatint register through the XC!\n");
cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
if (!thread->trapPending && !thread->inSyscall) {
cpu->squashFromXC(thread->tid);
@ -459,7 +491,7 @@ AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val)
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaXC::setFloatRegInt(int reg_idx, uint64_t val)
AlphaFullCPU<Impl>::AlphaXC::setFloatRegBits(int reg_idx, FloatRegBits val)
{
DPRINTF(Fault, "Setting floatint register through the XC!\n");
cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
@ -723,7 +755,7 @@ AlphaFullCPU<Impl>::processInterrupts()
template <class Impl>
void
AlphaFullCPU<Impl>::syscall(int tid)
AlphaFullCPU<Impl>::syscall(int64_t callnum, int tid)
{
DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
@ -734,7 +766,7 @@ AlphaFullCPU<Impl>::syscall(int tid)
++(this->thread[tid]->funcExeInst);
// Execute the actual syscall.
this->thread[tid]->syscall();
this->thread[tid]->syscall(callnum);
// Decrease funcExeInst by one as the normal commit will handle
// incrementing it.

View file

@ -29,11 +29,14 @@
#ifndef __CPU_O3_ALPHA_DYN_INST_HH__
#define __CPU_O3_ALPHA_DYN_INST_HH__
#include "arch/isa_traits.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_impl.hh"
class Packet;
/**
* Mostly implementation & ISA specific AlphaDynInst. As with most
* other classes in the new CPU model, it is templated on the Impl to
@ -56,6 +59,8 @@ class AlphaDynInst : public BaseDynInst<Impl>
typedef TheISA::RegIndex RegIndex;
/** Integer register index type. */
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
/** Misc register index type. */
typedef TheISA::MiscReg MiscReg;
@ -79,7 +84,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
Fault initiateAcc();
/** Completes the access. Only valid for memory operations. */
Fault completeAcc();
Fault completeAcc(Packet *pkt);
private:
/** Initializes variables. */
@ -123,7 +128,7 @@ class AlphaDynInst : public BaseDynInst<Impl>
bool simPalCheck(int palFunc);
#else
/** Calls a syscall. */
void syscall();
void syscall(int64_t callnum);
#endif
private:

View file

@ -96,15 +96,13 @@ AlphaDynInst<Impl>::initiateAcc()
template <class Impl>
Fault
AlphaDynInst<Impl>::completeAcc()
AlphaDynInst<Impl>::completeAcc(Packet *pkt)
{
if (this->isLoad()) {
this->fault = this->staticInst->completeAcc(this->req->data,
this,
this->fault = this->staticInst->completeAcc(pkt, this,
this->traceData);
} else if (this->isStore()) {
this->fault = this->staticInst->completeAcc((uint8_t*)&this->req->result,
this,
this->fault = this->staticInst->completeAcc(pkt, this,
this->traceData);
} else {
panic("Unknown type!");
@ -168,9 +166,9 @@ AlphaDynInst<Impl>::simPalCheck(int palFunc)
#else
template <class Impl>
void
AlphaDynInst<Impl>::syscall()
AlphaDynInst<Impl>::syscall(int64_t callnum)
{
this->cpu->syscall(this->threadNumber);
this->cpu->syscall(callnum, this->threadNumber);
}
#endif

View file

@ -35,8 +35,7 @@
class AlphaDTB;
class AlphaITB;
class FUPool;
class FunctionalMemory;
class MemInterface;
class MemObject;
class Process;
class System;
@ -60,7 +59,7 @@ class AlphaSimpleParams : public BaseFullCPU::Params
//Page Table
// PageTable *pTable;
FunctionalMemory *mem;
MemObject *mem;
BaseCPU *checker;
@ -69,8 +68,8 @@ class AlphaSimpleParams : public BaseFullCPU::Params
//
// Caches
//
MemInterface *icacheInterface;
MemInterface *dcacheInterface;
// MemInterface *icacheInterface;
// MemInterface *dcacheInterface;
unsigned cachePorts;

View file

@ -30,8 +30,8 @@
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/ozone/ozone_impl.hh"
#include "cpu/ozone/simple_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
template class TwobitBPredUnit<AlphaSimpleImpl>;
template class TwobitBPredUnit<OzoneImpl>;
template class TwobitBPredUnit<SimpleImpl>;
//template class TwobitBPredUnit<SimpleImpl>;

View file

@ -31,6 +31,7 @@
// For Addr type.
#include "arch/isa_traits.hh"
#include "base/misc.hh"
class DefaultBTB
{

View file

@ -34,7 +34,6 @@
#include "base/timebuf.hh"
#include "cpu/exetrace.hh"
#include "cpu/inst_seq.hh"
#include "mem/memory_interface.hh"
template <class>
class O3ThreadState;
@ -301,9 +300,6 @@ class DefaultCommit
/** Pointer to FullCPU. */
FullCPU *cpu;
/** Memory interface. Used for d-cache accesses. */
MemInterface *dcacheInterface;
std::vector<Thread *> thread;
Fault fetchFault;

View file

@ -64,8 +64,7 @@ DefaultCommit<Impl>::TrapEvent::description()
template <class Impl>
DefaultCommit<Impl>::DefaultCommit(Params *params)
: dcacheInterface(params->dcacheInterface),
squashCounter(0),
: squashCounter(0),
iewToCommitDelay(params->iewToCommitDelay),
commitToIEWDelay(params->commitToIEWDelay),
renameToROBDelay(params->renameToROBDelay),

View file

@ -46,6 +46,7 @@
#include "sim/stat_control.hh"
using namespace std;
using namespace TheISA;
BaseFullCPU::BaseFullCPU(Params *params)
: BaseCPU(params), cpu_id(0)
@ -121,14 +122,9 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
system(params->system),
memCtrl(system->memctrl),
physmem(system->physmem),
mem(params->mem),
#else
// pTable(params->pTable),
mem(params->workload[0]->getMemory()),
#endif // FULL_SYSTEM
mem(params->mem),
switchCount(0),
icacheInterface(params->icacheInterface),
dcacheInterface(params->dcacheInterface),
deferRegistration(params->deferRegistration),
numThreads(number_of_threads)
{
@ -782,6 +778,7 @@ FullO3CPU<Impl>::readFloatReg(int reg_idx)
template <class Impl>
FloatRegBits
FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
{
return regFile.readFloatRegBits(reg_idx, width);
}
@ -843,7 +840,7 @@ FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
int idx = reg_idx + TheISA::FP_Base_DepTag;
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
return regFile.readFloatRegSingle(phys_reg);
return regFile.readFloatReg(phys_reg);
}
template <class Impl>
@ -853,7 +850,7 @@ FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
int idx = reg_idx + TheISA::FP_Base_DepTag;
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
return regFile.readFloatRegDouble(phys_reg);
return regFile.readFloatReg(phys_reg, 64);
}
template <class Impl>
@ -863,7 +860,7 @@ FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
int idx = reg_idx + TheISA::FP_Base_DepTag;
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
return regFile.readFloatRegInt(phys_reg);
return regFile.readFloatRegBits(phys_reg);
}
template <class Impl>
@ -881,7 +878,7 @@ FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
{
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
regFile.setFloatRegSingle(phys_reg, val);
regFile.setFloatReg(phys_reg, val);
}
template <class Impl>
@ -890,7 +887,7 @@ FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
{
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
regFile.setFloatRegDouble(phys_reg, val);
regFile.setFloatReg(phys_reg, val, 64);
}
template <class Impl>
@ -899,7 +896,7 @@ FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
{
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
regFile.setFloatRegInt(phys_reg, val);
regFile.setFloatRegBits(phys_reg, val);
}
template <class Impl>

View file

@ -35,6 +35,7 @@
#include <set>
#include <vector>
#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "config/full_system.hh"
@ -50,7 +51,7 @@
template <class>
class Checker;
class ExecContext;
class MemInterface;
class MemObject;
class Process;
class BaseFullCPU : public BaseCPU
@ -63,6 +64,8 @@ class BaseFullCPU : public BaseCPU
void regStats();
int readCpuId() { return cpu_id; }
protected:
int cpu_id;
};
@ -71,6 +74,9 @@ template <class Impl>
class FullO3CPU : public BaseFullCPU
{
public:
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
// Typedefs from the Impl here.
typedef typename Impl::CPUPol CPUPolicy;
typedef typename Impl::Params Params;
@ -226,14 +232,6 @@ class FullO3CPU : public BaseFullCPU
int getDataAsid(unsigned tid)
{ return regFile.miscRegs[tid].getDataAsid(); }
#else
/** Check if this address is a valid instruction address. */
bool validInstAddr(Addr addr,unsigned tid)
{ return thread[tid]->validInstAddr(addr); }
/** Check if this address is a valid data address. */
bool validDataAddr(Addr addr,unsigned tid)
{ return thread[tid]->validDataAddr(addr); }
/** Get instruction asid. */
int getInstAsid(unsigned tid)
{ return thread[tid]->asid; }
@ -259,13 +257,13 @@ class FullO3CPU : public BaseFullCPU
void setIntReg(int reg_idx, uint64_t val);
void setFloatReg(int reg_idx, FloatReg val, int width);
void setFloatReg(int reg_idx, FloatReg val);
void setFloatReg(int reg_idx, FloatReg val, int width);
void setFloatRegBits(int reg_idx, FloatRegBits val);
void setFloatRegBits(int reg_idx, FloatRegBits val);
void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
uint64_t readArchIntReg(int reg_idx, unsigned tid);
@ -464,7 +462,7 @@ class FullO3CPU : public BaseFullCPU
#endif
/** Pointer to memory. */
FunctionalMemory *mem;
MemObject *mem;
Sampler *sampler;

View file

@ -29,10 +29,12 @@
#ifndef __CPU_O3_FETCH_HH__
#define __CPU_O3_FETCH_HH__
#include "arch/utility.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/pc_event.hh"
#include "mem/mem_interface.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
#include "sim/eventq.hh"
class Sampler;
@ -65,6 +67,32 @@ class DefaultFetch
typedef TheISA::MachInst MachInst;
typedef TheISA::ExtMachInst ExtMachInst;
class IcachePort : public Port
{
protected:
DefaultFetch<Impl> *fetch;
public:
IcachePort(DefaultFetch<Impl> *_fetch)
: Port(_fetch->name() + "-iport"), fetch(_fetch)
{ }
protected:
virtual Tick recvAtomic(PacketPtr pkt);
virtual void recvFunctional(PacketPtr pkt);
virtual void recvStatusChange(Status status);
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
virtual bool recvTiming(PacketPtr pkt);
virtual void recvRetry();
};
public:
/** Overall fetch status. Used to determine if the CPU can
* deschedule itsef due to a lack of activity.
@ -84,8 +112,9 @@ class DefaultFetch
TrapPending,
QuiescePending,
SwitchOut,
IcacheMissStall,
IcacheMissComplete
IcacheWaitResponse,
IcacheRetry,
IcacheAccessComplete
};
/** Fetching Policy, Add new policies here.*/
@ -110,28 +139,6 @@ class DefaultFetch
/** List that has the threads organized by priority. */
std::list<unsigned> priorityList;
public:
class CacheCompletionEvent : public Event
{
private:
MemReqPtr req;
/** Pointer to fetch. */
DefaultFetch *fetch;
/** Thread id. */
// unsigned threadId;
public:
/** Constructs a cache completion event, which tells fetch when the
* cache miss is complete.
*/
CacheCompletionEvent(MemReqPtr &_req, DefaultFetch *_fetch);
/** Processes cache completion event. */
virtual void process();
/** Returns the description of the cache completion event. */
virtual const char *description();
};
public:
/** DefaultFetch constructor. */
DefaultFetch(Params *params);
@ -161,7 +168,7 @@ class DefaultFetch
void initStage();
/** Processes cache completion event. */
void processCacheCompletion(MemReqPtr &req);
void processCacheCompletion(PacketPtr pkt);
void switchOut();
@ -295,8 +302,10 @@ class DefaultFetch
/** Wire used to write any information heading to decode. */
typename TimeBuffer<FetchStruct>::wire toDecode;
MemObject *mem;
/** Icache interface. */
MemInterface *icacheInterface;
IcachePort *icachePort;
/** BPredUnit. */
BPredUnit branchPred;
@ -305,8 +314,8 @@ class DefaultFetch
Addr nextPC[Impl::MaxThreads];
/** Memory request used to access cache. */
MemReqPtr memReq[Impl::MaxThreads];
/** Memory packet used to access cache. */
PacketPtr memPkt[Impl::MaxThreads];
/** Variable that tracks if fetch has written to the time buffer this
* cycle. Used to tell CPU if there is activity this cycle.

View file

@ -27,12 +27,13 @@
*/
#include "arch/isa_traits.hh"
#include "arch/utility.hh"
#include "cpu/exetrace.hh"
#include "cpu/o3/fetch.hh"
#include "mem/base_mem.hh"
#include "mem/mem_interface.hh"
#include "mem/mem_req.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
#include "sim/byteswap.hh"
#include "sim/host.hh"
#include "sim/root.hh"
#if FULL_SYSTEM
@ -42,42 +43,67 @@
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/system.hh"
#else // !FULL_SYSTEM
#include "mem/functional/functional.hh"
#endif // FULL_SYSTEM
#include <algorithm>
using namespace std;
using namespace TheISA;
template<class Impl>
DefaultFetch<Impl>::CacheCompletionEvent::CacheCompletionEvent(MemReqPtr &_req,
DefaultFetch *_fetch)
: Event(&mainEventQueue, Delayed_Writeback_Pri),
req(_req),
fetch(_fetch)
Tick
DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
{
this->setFlags(Event::AutoDelete);
panic("DefaultFetch doesn't expect recvAtomic callback!");
return curTick;
}
template<class Impl>
void
DefaultFetch<Impl>::CacheCompletionEvent::process()
DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
{
fetch->processCacheCompletion(req);
panic("DefaultFetch doesn't expect recvFunctional callback!");
}
template<class Impl>
const char *
DefaultFetch<Impl>::CacheCompletionEvent::description()
void
DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status)
{
return "DefaultFetch cache completion event";
if (status == RangeChange)
return;
panic("DefaultFetch doesn't expect recvStatusChange callback!");
}
template<class Impl>
bool
DefaultFetch<Impl>::IcachePort::recvTiming(Packet *pkt)
{
fetch->processCacheCompletion(pkt);
return true;
}
template<class Impl>
void
DefaultFetch<Impl>::IcachePort::recvRetry()
{
panic("DefaultFetch doesn't support retry yet.");
// we shouldn't get a retry unless we have a packet that we're
// waiting to transmit
/*
assert(cpu->dcache_pkt != NULL);
assert(cpu->_status == DcacheRetry);
Packet *tmp = cpu->dcache_pkt;
if (sendTiming(tmp)) {
cpu->_status = DcacheWaitResponse;
cpu->dcache_pkt = NULL;
}
*/
}
template<class Impl>
DefaultFetch<Impl>::DefaultFetch(Params *params)
: icacheInterface(params->icacheInterface),
branchPred(params),
: branchPred(params),
decodeToFetchDelay(params->decodeToFetchDelay),
renameToFetchDelay(params->renameToFetchDelay),
iewToFetchDelay(params->iewToFetchDelay),
@ -122,7 +148,7 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
}
// Size of cache block.
cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64;
cacheBlkSize = 64;
// Create mask to get rid of offset bits.
cacheBlkMask = (cacheBlkSize - 1);
@ -133,8 +159,7 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
priorityList.push_back(tid);
// Create a new memory request.
memReq[tid] = NULL;
memPkt[tid] = NULL;
// Create space to store a cache line.
cacheData[tid] = new uint8_t[cacheBlkSize];
@ -253,6 +278,9 @@ DefaultFetch<Impl>::setCPU(FullCPU *cpu_ptr)
DPRINTF(Fetch, "Setting the CPU pointer.\n");
cpu = cpu_ptr;
// Name is finally available, so create the port.
icachePort = new IcachePort(this);
// Fetch needs to start fetching instructions at the very beginning,
// so it must start up in active state.
switchToActive();
@ -315,9 +343,9 @@ DefaultFetch<Impl>::initStage()
template<class Impl>
void
DefaultFetch<Impl>::processCacheCompletion(MemReqPtr &req)
DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
{
unsigned tid = req->thread_num;
unsigned tid = pkt->req->getThreadNum();
DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid);
@ -325,10 +353,11 @@ DefaultFetch<Impl>::processCacheCompletion(MemReqPtr &req)
// to return.
// Can keep track of how many cache accesses go unused due to
// misspeculation here.
if (fetchStatus[tid] != IcacheMissStall ||
req != memReq[tid] ||
if (fetchStatus[tid] != IcacheWaitResponse ||
pkt != memPkt[tid] ||
isSwitchedOut()) {
++fetchIcacheSquashes;
delete pkt;
return;
}
@ -341,17 +370,19 @@ DefaultFetch<Impl>::processCacheCompletion(MemReqPtr &req)
switchToActive();
// Only switch to IcacheMissComplete if we're not stalled as well.
// Only switch to IcacheAccessComplete if we're not stalled as well.
if (checkStall(tid)) {
fetchStatus[tid] = Blocked;
} else {
fetchStatus[tid] = IcacheMissComplete;
fetchStatus[tid] = IcacheAccessComplete;
}
// memcpy(cacheData[tid], memReq[tid]->data, memReq[tid]->size);
// Reset the mem req to NULL.
memReq[tid] = NULL;
delete pkt->req;
delete pkt;
memPkt[tid] = NULL;
}
template <class Impl>
@ -475,18 +506,15 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Setup the memReq to do a read of the first instruction's address.
// Set the appropriate read size and flags as well.
memReq[tid] = new MemReq();
// Build request here.
RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, flags,
fetch_PC, cpu->readCpuId(), tid);
memReq[tid]->asid = tid;
memReq[tid]->thread_num = tid;
memReq[tid]->data = new uint8_t[64];
memReq[tid]->xc = cpu->xcBase(tid);
memReq[tid]->cmd = Read;
memReq[tid]->reset(fetch_PC, cacheBlkSize, flags);
memPkt[tid] = NULL;
// Translate the instruction request.
//#if FULL_SYSTEM
fault = cpu->translateInstReq(memReq[tid]);
fault = cpu->translateInstReq(mem_req);
//#else
// fault = pTable->translate(memReq[tid]);
//#endif
@ -508,48 +536,31 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
}
#endif
// Build packet here.
PacketPtr data_pkt = new Packet(mem_req,
Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(cacheData[tid]);
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
fault = cpu->mem->read(memReq[tid], cacheData[tid]);
// This read may change when the mem interface changes.
fetchedCacheLines++;
// Now do the timing access to see whether or not the instruction
// exists within the cache.
if (icacheInterface && !icacheInterface->isBlocked()) {
DPRINTF(Fetch, "Doing cache access.\n");
memReq[tid]->completionEvent = NULL;
memReq[tid]->time = curTick;
MemAccessResult result = icacheInterface->access(memReq[tid]);
fetchedCacheLines++;
// If the cache missed, then schedule an event to wake
// up this stage once the cache miss completes.
// @todo: Possibly allow for longer than 1 cycle cache hits.
if (result != MA_HIT && icacheInterface->doEvents()) {
memReq[tid]->completionEvent =
new CacheCompletionEvent(memReq[tid], this);
lastIcacheStall[tid] = curTick;
DPRINTF(Activity, "[tid:%i]: Activity: Stalling due to I-cache "
"miss.\n", tid);
fetchStatus[tid] = IcacheMissStall;
} else {
DPRINTF(Fetch, "[tid:%i]: I-Cache hit. Doing Instruction "
"read.\n", tid);
// memcpy(cacheData[tid], memReq[tid]->data, memReq[tid]->size);
}
} else {
if (!icachePort->sendTiming(data_pkt)) {
DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
ret_fault = NoFault;
return false;
}
DPRINTF(Fetch, "Doing cache access.\n");
lastIcacheStall[tid] = curTick;
DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache "
"response.\n", tid);
fetchStatus[tid] = IcacheWaitResponse;
}
ret_fault = fault;
@ -567,10 +578,11 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid)
nextPC[tid] = new_PC + instSize;
// Clear the icache miss if it's outstanding.
if (fetchStatus[tid] == IcacheMissStall && icacheInterface) {
if (fetchStatus[tid] == IcacheWaitResponse) {
DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n",
tid);
memReq[tid] = NULL;
delete memPkt[tid];
memPkt[tid] = NULL;
}
fetchStatus[tid] = Squashing;
@ -632,12 +644,12 @@ DefaultFetch<Impl>::updateFetchStatus()
if (fetchStatus[tid] == Running ||
fetchStatus[tid] == Squashing ||
fetchStatus[tid] == IcacheMissComplete) {
fetchStatus[tid] == IcacheAccessComplete) {
if (_status == Inactive) {
DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid);
if (fetchStatus[tid] == IcacheMissComplete) {
if (fetchStatus[tid] == IcacheAccessComplete) {
DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache"
"completion\n",tid);
}
@ -831,7 +843,7 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
}
}
if (checkStall(tid) && fetchStatus[tid] != IcacheMissStall) {
if (checkStall(tid) && fetchStatus[tid] != IcacheWaitResponse) {
DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid);
fetchStatus[tid] = Blocked;
@ -882,7 +894,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
// If returning from the delay of a cache miss, then update the status
// to running, otherwise do the cache access. Possibly move this up
// to tick() function.
if (fetchStatus[tid] == IcacheMissComplete) {
if (fetchStatus[tid] == IcacheAccessComplete) {
DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n",
tid);
@ -905,11 +917,11 @@ DefaultFetch<Impl>::fetch(bool &status_change)
++fetchBlockedCycles;
} else if (fetchStatus[tid] == Squashing) {
++fetchSquashCycles;
} else if (fetchStatus[tid] == IcacheMissStall) {
} else if (fetchStatus[tid] == IcacheWaitResponse) {
++icacheStallCycles;
}
// Status is Idle, Squashing, Blocked, or IcacheMissStall, so
// Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
// fetch should do nothing.
return;
}
@ -917,7 +929,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
++fetchCycles;
// If we had a stall due to an icache miss, then return.
if (fetchStatus[tid] == IcacheMissStall) {
if (fetchStatus[tid] == IcacheWaitResponse) {
++icacheStallCycles;
status_change = true;
return;
@ -1026,7 +1038,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
} else {
// We shouldn't be in an icache miss and also have a fault (an ITB
// miss)
if (fetchStatus[tid] == IcacheMissStall) {
if (fetchStatus[tid] == IcacheWaitResponse) {
panic("Fetch should have exited prior to this!");
}
@ -1107,7 +1119,7 @@ DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority)
int tid = *((*activeThreads).begin());
if (fetchStatus[tid] == Running ||
fetchStatus[tid] == IcacheMissComplete ||
fetchStatus[tid] == IcacheAccessComplete ||
fetchStatus[tid] == Idle) {
return tid;
} else {
@ -1133,7 +1145,7 @@ DefaultFetch<Impl>::roundRobin()
assert(high_pri <= numThreads);
if (fetchStatus[high_pri] == Running ||
fetchStatus[high_pri] == IcacheMissComplete ||
fetchStatus[high_pri] == IcacheAccessComplete ||
fetchStatus[high_pri] == Idle) {
priorityList.erase(pri_iter);
@ -1167,7 +1179,7 @@ DefaultFetch<Impl>::iqCount()
unsigned high_pri = PQ.top();
if (fetchStatus[high_pri] == Running ||
fetchStatus[high_pri] == IcacheMissComplete ||
fetchStatus[high_pri] == IcacheAccessComplete ||
fetchStatus[high_pri] == Idle)
return high_pri;
else
@ -1198,7 +1210,7 @@ DefaultFetch<Impl>::lsqCount()
unsigned high_pri = PQ.top();
if (fetchStatus[high_pri] == Running ||
fetchStatus[high_pri] == IcacheMissComplete ||
fetchStatus[high_pri] == IcacheAccessComplete ||
fetchStatus[high_pri] == Idle)
return high_pri;
else

View file

@ -33,6 +33,7 @@
#include <queue>
#include "arch/isa_traits.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/traceflags.hh"
#include "cpu/o3/comm.hh"

View file

@ -35,7 +35,7 @@
#include <vector>
#include "base/sched_list.hh"
#include "encumbered/cpu/full/op_class.hh"
#include "cpu/op_class.hh"
#include "sim/sim_object.hh"
class FUDesc;

View file

@ -110,25 +110,6 @@ class DefaultIEW
/** Writeback status. */
StageStatus wbStatus;
public:
/** LdWriteback event for a load completion. */
class LdWritebackEvent : public Event {
private:
/** Instruction that is writing back data to the register file. */
DynInstPtr inst;
/** Pointer to IEW stage. */
DefaultIEW<Impl> *iewStage;
public:
/** Constructs a load writeback event. */
LdWritebackEvent(DynInstPtr &_inst, DefaultIEW<Impl> *_iew);
/** Processes writeback event. */
virtual void process();
/** Returns the description of the writeback event. */
virtual const char *description();
};
public:
/** Constructs a DefaultIEW with the given parameters. */
DefaultIEW(Params *params);

View file

@ -38,58 +38,6 @@
using namespace std;
template<class Impl>
DefaultIEW<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
DefaultIEW<Impl> *_iew)
: Event(&mainEventQueue), inst(_inst), iewStage(_iew)
{
this->setFlags(Event::AutoDelete);
}
template<class Impl>
void
DefaultIEW<Impl>::LdWritebackEvent::process()
{
DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum);
DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
//iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
if (iewStage->isSwitchedOut()) {
inst = NULL;
return;
} else if (inst->isSquashed()) {
iewStage->wakeCPU();
inst = NULL;
return;
}
iewStage->wakeCPU();
if (!inst->isExecuted()) {
inst->setExecuted();
// Complete access to copy data to proper place.
if (inst->isStore()) {
inst->completeAcc();
}
}
// Need to insert instruction into queue to commit
iewStage->instToCommit(inst);
iewStage->activityThisCycle();
inst = NULL;
}
template<class Impl>
const char *
DefaultIEW<Impl>::LdWritebackEvent::description()
{
return "Load writeback event";
}
template<class Impl>
DefaultIEW<Impl>::DefaultIEW(Params *params)
: // @todo: Make this into a parameter.
@ -1280,7 +1228,7 @@ DefaultIEW<Impl>::executeInsts()
ldstQueue.executeStore(inst);
// If the store had a fault then it may not have a mem req
if (inst->req && !(inst->req->flags & LOCKED)) {
if (inst->req && !(inst->req->getFlags() & LOCKED)) {
inst->setExecuted();
instToCommit(inst);
@ -1556,7 +1504,7 @@ DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
else
iewExecutedInsts++;
#else
iewExecutedInsts[thread_number]++;
iewExecutedInsts++;
#endif
//

View file

@ -38,7 +38,7 @@
#include "base/timebuf.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/dep_graph.hh"
#include "encumbered/cpu/full/op_class.hh"
#include "cpu/op_class.hh"
#include "sim/host.hh"
class FUPool;

View file

@ -64,8 +64,7 @@ InstructionQueue<Impl>::FUCompletion::description()
template <class Impl>
InstructionQueue<Impl>::InstructionQueue(Params *params)
: dcacheInterface(params->dcacheInterface),
fuPool(params->fuPool),
: fuPool(params->fuPool),
numEntries(params->numIQEntries),
totalWidth(params->issueWidth),
numPhysIntRegs(params->numPhysIntRegs),

View file

@ -36,7 +36,7 @@
#include "cpu/inst_seq.hh"
//#include "cpu/o3/cpu_policy.hh"
#include "cpu/o3/lsq_unit.hh"
#include "mem/mem_interface.hh"
#include "mem/port.hh"
//#include "mem/page_table.hh"
#include "sim/sim_object.hh"
@ -259,13 +259,13 @@ class LSQ {
/** Executes a read operation, using the load specified at the load index. */
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx);
Fault read(RequestPtr req, T &data, int load_idx);
/** Executes a store operation, using the store specified at the store
* index.
*/
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx);
Fault write(RequestPtr req, T &data, int store_idx);
private:
/** The LSQ policy for SMT mode. */
@ -304,9 +304,9 @@ class LSQ {
template <class Impl>
template <class T>
Fault
LSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
LSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
{
unsigned tid = req->thread_num;
unsigned tid = req->getThreadNum();
return thread[tid].read(req, data, load_idx);
}
@ -314,9 +314,9 @@ LSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
template <class Impl>
template <class T>
Fault
LSQ<Impl>::write(MemReqPtr &req, T &data, int store_idx)
LSQ<Impl>::write(RequestPtr req, T &data, int store_idx)
{
unsigned tid = req->thread_num;
unsigned tid = req->getThreadNum();
return thread[tid].write(req, data, store_idx);
}

View file

@ -37,7 +37,8 @@
#include "config/full_system.hh"
#include "base/hashmap.hh"
#include "cpu/inst_seq.hh"
#include "mem/mem_interface.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
//#include "mem/page_table.hh"
//#include "sim/debug.hh"
//#include "sim/sim_object.hh"
@ -65,31 +66,6 @@ class LSQUnit {
typedef typename Impl::CPUPol::IEW IEW;
typedef typename Impl::CPUPol::IssueStruct IssueStruct;
private:
class StoreCompletionEvent : public Event {
public:
/** Constructs a store completion event. */
StoreCompletionEvent(int store_idx, Event *wb_event, LSQUnit *lsq_ptr);
/** Processes the store completion event. */
void process();
/** Returns the description of this event. */
const char *description();
/** The writeback event for the store. Needed for store
* conditionals.
*/
Event *wbEvent;
private:
/** The store index of the store being written back. */
int storeIdx;
private:
/** The pointer to the LSQ unit that issued the store. */
LSQUnit<Impl> *lsqPtr;
};
public:
/** Constructs an LSQ unit. init() must be called prior to use. */
LSQUnit();
@ -102,8 +78,7 @@ class LSQUnit {
std::string name() const;
/** Sets the CPU pointer. */
void setCPU(FullCPU *cpu_ptr)
{ cpu = cpu_ptr; }
void setCPU(FullCPU *cpu_ptr);
/** Sets the IEW stage pointer. */
void setIEW(IEW *iew_ptr)
@ -150,6 +125,10 @@ class LSQUnit {
/** Writes back stores. */
void writebackStores();
void completeDataAccess(PacketPtr pkt);
void completeStoreDataAccess(DynInstPtr &inst);
// @todo: Include stats in the LSQ unit.
//void regStats();
@ -221,8 +200,8 @@ class LSQUnit {
/** Returns if the LSQ unit will writeback on this cycle. */
bool willWB() { return storeQueue[storeWBIdx].canWB &&
!storeQueue[storeWBIdx].completed &&
!dcacheInterface->isBlocked(); }
!storeQueue[storeWBIdx].completed/* &&
!dcacheInterface->isBlocked()*/; }
private:
/** Completes the store at the specified index. */
@ -248,8 +227,37 @@ class LSQUnit {
/** Pointer to the IEW stage. */
IEW *iewStage;
MemObject *mem;
class DcachePort : public Port
{
protected:
FullCPU *cpu;
LSQUnit *lsq;
public:
DcachePort(FullCPU *_cpu, LSQUnit *_lsq)
: Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
{ }
protected:
virtual Tick recvAtomic(PacketPtr pkt);
virtual void recvFunctional(PacketPtr pkt);
virtual void recvStatusChange(Status status);
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
virtual bool recvTiming(PacketPtr pkt);
virtual void recvRetry();
};
/** Pointer to the D-cache. */
MemInterface *dcacheInterface;
DcachePort *dcachePort;
/** Pointer to the page table. */
// PageTable *pTable;
@ -270,8 +278,8 @@ class LSQUnit {
/** The store instruction. */
DynInstPtr inst;
/** The memory request for the store. */
MemReqPtr req;
/** The request for the store. */
RequestPtr req;
/** The size of the store. */
int size;
/** The store data. */
@ -382,11 +390,11 @@ class LSQUnit {
public:
/** Executes the load at the given index. */
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx);
Fault read(Request *req, T &data, int load_idx);
/** Executes the store at the given index. */
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx);
Fault write(Request *req, T &data, int store_idx);
/** Returns the index of the head load instruction. */
int getLoadHead() { return loadHead; }
@ -421,41 +429,39 @@ class LSQUnit {
template <class Impl>
template <class T>
Fault
LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx)
LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
{
assert(loadQueue[load_idx]);
DynInstPtr load_inst = loadQueue[load_idx];
assert(!loadQueue[load_idx]->isExecuted());
assert(load_inst);
assert(!load_inst->isExecuted());
// Make sure this isn't an uncacheable access
// A bit of a hackish way to get uncached accesses to work only if they're
// at the head of the LSQ and are ready to commit (at the head of the ROB
// too).
if (req->flags & UNCACHEABLE &&
(load_idx != loadHead || !loadQueue[load_idx]->reachedCommit)) {
iewStage->rescheduleMemInst(loadQueue[load_idx]);
if (req->getFlags() & UNCACHEABLE &&
(load_idx != loadHead || !load_inst->reachedCommit)) {
iewStage->rescheduleMemInst(load_inst);
return TheISA::genMachineCheckFault();
}
// Check the SQ for any previous stores that might lead to forwarding
int store_idx = loadQueue[load_idx]->sqIdx;
int store_idx = load_inst->sqIdx;
int store_size = 0;
DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
"storeHead: %i addr: %#x\n",
load_idx, store_idx, storeHead, req->paddr);
load_idx, store_idx, storeHead, req->getPaddr());
#if 0
if (req->flags & LOCKED) {
cpu->lockAddr = req->paddr;
if (req->getFlags() & LOCKED) {
cpu->lockAddr = req->getPaddr();
cpu->lockFlag = true;
}
#endif
req->cmd = Read;
assert(!req->completionEvent);
req->completionEvent = NULL;
req->time = curTick;
while (store_idx != -1) {
// End once we've reached the top of the LSQ
@ -477,44 +483,45 @@ LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx)
// Check if the store data is within the lower and upper bounds of
// addresses that the request needs.
bool store_has_lower_limit =
req->vaddr >= storeQueue[store_idx].inst->effAddr;
req->getVaddr() >= storeQueue[store_idx].inst->effAddr;
bool store_has_upper_limit =
(req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr +
store_size);
(req->getVaddr() + req->getSize()) <=
(storeQueue[store_idx].inst->effAddr + store_size);
bool lower_load_has_store_part =
req->vaddr < (storeQueue[store_idx].inst->effAddr +
req->getVaddr() < (storeQueue[store_idx].inst->effAddr +
store_size);
bool upper_load_has_store_part =
(req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr;
(req->getVaddr() + req->getSize()) >
storeQueue[store_idx].inst->effAddr;
// If the store's data has all of the data needed, we can forward.
if (store_has_lower_limit && store_has_upper_limit) {
// Get shift amount for offset into the store's data.
int shift_amt = req->vaddr & (store_size - 1);
int shift_amt = req->getVaddr() & (store_size - 1);
// @todo: Magic number, assumes byte addressing
shift_amt = shift_amt << 3;
// Cast this to type T?
data = storeQueue[store_idx].data >> shift_amt;
assert(!req->data);
req->data = new uint8_t[64];
assert(!load_inst->memData);
load_inst->memData = new uint8_t[64];
memcpy(req->data, &data, req->size);
memcpy(load_inst->memData, &data, req->getSize());
DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
"addr %#x, data %#x\n",
store_idx, req->vaddr, *(req->data));
typename IEW::LdWritebackEvent *wb =
new typename IEW::LdWritebackEvent(loadQueue[load_idx],
iewStage);
store_idx, req->getVaddr(), *(load_inst->memData));
/*
typename LdWritebackEvent *wb =
new typename LdWritebackEvent(load_inst,
iewStage);
// We'll say this has a 1 cycle load-store forwarding latency
// for now.
// @todo: Need to make this a parameter.
wb->schedule(curTick);
*/
// Should keep track of stat for forwarded data
return NoFault;
} else if ((store_has_lower_limit && lower_load_has_store_part) ||
@ -533,7 +540,7 @@ LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx)
// load that needs to do so.
if (!stalled ||
(stalled &&
loadQueue[load_idx]->seqNum <
load_inst->seqNum <
loadQueue[stallingLoadIdx]->seqNum)) {
stalled = true;
stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
@ -542,82 +549,72 @@ LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx)
// Tell IQ/mem dep unit that this instruction will need to be
// rescheduled eventually
iewStage->rescheduleMemInst(loadQueue[load_idx]);
iewStage->rescheduleMemInst(load_inst);
// Do not generate a writeback event as this instruction is not
// complete.
DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
"Store idx %i to load addr %#x\n",
store_idx, req->vaddr);
store_idx, req->getVaddr());
return NoFault;
}
}
// If there's no forwarding case, then go access memory
DynInstPtr inst = loadQueue[load_idx];
DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n",
loadQueue[load_idx]->seqNum, loadQueue[load_idx]->readPC());
load_inst->seqNum, load_inst->readPC());
assert(!req->data);
req->data = new uint8_t[64];
Fault fault = cpu->read(req, data);
memcpy(req->data, &data, sizeof(T));
assert(!load_inst->memData);
load_inst->memData = new uint8_t[64];
++usedPorts;
DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
load_inst->readPC());
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(load_inst->memData);
// if we have a cache, do cache access too
if (fault == NoFault && dcacheInterface) {
if (dcacheInterface->isBlocked()) {
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
return NoFault;
// Record that the load was blocked due to memory. This
// load will squash all instructions after it, be
// refetched, and re-executed.
isLoadBlocked = true;
loadBlockedHandled = false;
blockedLoadSeqNum = inst->seqNum;
// No fault occurred, even though the interface is blocked.
if (!dcachePort->sendTiming(data_pkt)) {
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
return NoFault;
}
DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
loadQueue[load_idx]->readPC());
assert(!req->completionEvent);
req->completionEvent =
new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage);
MemAccessResult result = dcacheInterface->access(req);
assert(dcacheInterface->doEvents());
if (result != MA_HIT) {
DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
inst->seqNum);
} else {
DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
inst->seqNum);
}
// Record that the load was blocked due to memory. This
// load will squash all instructions after it, be
// refetched, and re-executed.
isLoadBlocked = true;
loadBlockedHandled = false;
blockedLoadSeqNum = load_inst->seqNum;
// No fault occurred, even though the interface is blocked.
return NoFault;
}
return fault;
if (data_pkt->result != Packet::Success) {
DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
load_inst->seqNum);
} else {
DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
load_inst->seqNum);
}
return NoFault;
}
template <class Impl>
template <class T>
Fault
LSQUnit<Impl>::write(MemReqPtr &req, T &data, int store_idx)
LSQUnit<Impl>::write(Request *req, T &data, int store_idx)
{
assert(storeQueue[store_idx].inst);
DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x"
" | storeHead:%i [sn:%i]\n",
store_idx, req->paddr, data, storeHead,
store_idx, req->getPaddr(), data, storeHead,
storeQueue[store_idx].inst->seqNum);
storeQueue[store_idx].req = req;

View file

@ -29,23 +29,50 @@
#include "cpu/checker/cpu.hh"
#include "cpu/o3/lsq_unit.hh"
#include "base/str.hh"
#include "mem/request.hh"
template <class Impl>
LSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx,
Event *wb_event,
LSQUnit<Impl> *lsq_ptr)
: Event(&mainEventQueue),
wbEvent(wb_event),
storeIdx(store_idx),
lsqPtr(lsq_ptr)
template<class Impl>
void
LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
{
this->setFlags(Event::AutoDelete);
/*
DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum);
DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
//iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
if (iewStage->isSwitchedOut()) {
inst = NULL;
return;
} else if (inst->isSquashed()) {
iewStage->wakeCPU();
inst = NULL;
return;
}
iewStage->wakeCPU();
if (!inst->isExecuted()) {
inst->setExecuted();
// Complete access to copy data to proper place.
inst->completeAcc();
}
// Need to insert instruction into queue to commit
iewStage->instToCommit(inst);
iewStage->activityThisCycle();
inst = NULL;
*/
}
template <class Impl>
template<class Impl>
void
LSQUnit<Impl>::StoreCompletionEvent::process()
LSQUnit<Impl>::completeStoreDataAccess(DynInstPtr &inst)
{
/*
DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx);
DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx);
@ -55,16 +82,62 @@ LSQUnit<Impl>::StoreCompletionEvent::process()
return;
lsqPtr->cpu->wakeCPU();
if (wbEvent)
wbEvent->process();
if (wb)
lsqPtr->completeDataAccess(storeIdx);
lsqPtr->completeStore(storeIdx);
*/
}
template <class Impl>
const char *
LSQUnit<Impl>::StoreCompletionEvent::description()
Tick
LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
{
return "LSQ store completion event";
panic("O3CPU model does not work with atomic mode!");
return curTick;
}
template <class Impl>
void
LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
{
panic("O3CPU doesn't expect recvFunctional callback!");
}
template <class Impl>
void
LSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
{
if (status == RangeChange)
return;
panic("O3CPU doesn't expect recvStatusChange callback!");
}
template <class Impl>
bool
LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
{
lsq->completeDataAccess(pkt);
return true;
}
template <class Impl>
void
LSQUnit<Impl>::DcachePort::recvRetry()
{
panic("Retry unsupported for now!");
// we shouldn't get a retry unless we have a packet that we're
// waiting to transmit
/*
assert(cpu->dcache_pkt != NULL);
assert(cpu->_status == DcacheRetry);
PacketPtr tmp = cpu->dcache_pkt;
if (sendTiming(tmp)) {
cpu->_status = DcacheWaitResponse;
cpu->dcache_pkt = NULL;
}
*/
}
template <class Impl>
@ -78,7 +151,6 @@ template<class Impl>
void
LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
unsigned maxSQEntries, unsigned id)
{
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
@ -100,13 +172,23 @@ LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
usedPorts = 0;
cachePorts = params->cachePorts;
dcacheInterface = params->dcacheInterface;
Port *mem_dport = params->mem->getPort("");
dcachePort->setPeer(mem_dport);
mem_dport->setPeer(dcachePort);
memDepViolator = NULL;
blockedLoadSeqNum = 0;
}
template<class Impl>
void
LSQUnit<Impl>::setCPU(FullCPU *cpu_ptr)
{
cpu = cpu_ptr;
dcachePort = new DcachePort(cpu, this);
}
template<class Impl>
std::string
LSQUnit<Impl>::name() const
@ -151,58 +233,6 @@ LSQUnit<Impl>::switchOut()
loadQueue[i] = NULL;
assert(storesToWB == 0);
while (storesToWB > 0 &&
storeWBIdx != storeTail &&
storeQueue[storeWBIdx].inst &&
storeQueue[storeWBIdx].canWB) {
if (storeQueue[storeWBIdx].size == 0 ||
storeQueue[storeWBIdx].inst->isDataPrefetch() ||
storeQueue[storeWBIdx].committed ||
storeQueue[storeWBIdx].req->flags & LOCKED) {
incrStIdx(storeWBIdx);
continue;
}
assert(storeQueue[storeWBIdx].req);
assert(!storeQueue[storeWBIdx].committed);
MemReqPtr req = storeQueue[storeWBIdx].req;
storeQueue[storeWBIdx].committed = true;
req->cmd = Write;
req->completionEvent = NULL;
req->time = curTick;
assert(!req->data);
req->data = new uint8_t[64];
memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
"to Addr:%#x, data:%#x [sn:%lli]\n",
storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
req->paddr, *(req->data),
storeQueue[storeWBIdx].inst->seqNum);
switch(storeQueue[storeWBIdx].size) {
case 1:
cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
break;
case 2:
cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
break;
case 4:
cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
break;
case 8:
cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
break;
default:
panic("Unexpected store size!\n");
}
incrStIdx(storeWBIdx);
}
}
template<class Impl>
@ -380,8 +410,7 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
inst->readPC(),inst->seqNum);
// load_fault = inst->initiateAcc();
load_fault = inst->execute();
load_fault = inst->initiateAcc();
// If the instruction faulted, then we need to send it along to commit
// without the instruction completing.
@ -539,13 +568,13 @@ LSQUnit<Impl>::writebackStores()
continue;
}
/*
if (dcacheInterface && dcacheInterface->isBlocked()) {
DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
" is blocked!\n");
break;
}
*/
++usedPorts;
if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
@ -557,59 +586,31 @@ LSQUnit<Impl>::writebackStores()
assert(storeQueue[storeWBIdx].req);
assert(!storeQueue[storeWBIdx].committed);
MemReqPtr req = storeQueue[storeWBIdx].req;
DynInstPtr inst = storeQueue[storeWBIdx].inst;
Request *req = storeQueue[storeWBIdx].req;
storeQueue[storeWBIdx].committed = true;
req->cmd = Write;
req->completionEvent = NULL;
req->time = curTick;
assert(!req->data);
req->data = new uint8_t[64];
memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size);
assert(!inst->memData);
inst->memData = new uint8_t[64];
memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, req->getSize());
PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
data_pkt->dataStatic(inst->memData);
DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
"to Addr:%#x, data:%#x [sn:%lli]\n",
storeWBIdx,storeQueue[storeWBIdx].inst->readPC(),
req->paddr, *(req->data),
storeWBIdx, storeQueue[storeWBIdx].inst->readPC(),
req->getPaddr(), *(inst->memData),
storeQueue[storeWBIdx].inst->seqNum);
switch(storeQueue[storeWBIdx].size) {
case 1:
cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data);
break;
case 2:
cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data);
break;
case 4:
cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data);
break;
case 8:
cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data);
break;
default:
panic("Unexpected store size!\n");
}
// Stores other than store conditionals are completed at this
// time. Mark them as completed and, if we have a checker,
// tell it that the instruction is completed.
// @todo: Figure out what time I can say stores are complete in
// the timing memory.
if (!(req->flags & LOCKED)) {
storeQueue[storeWBIdx].inst->setCompleted();
if (cpu->checker) {
cpu->checker->tick(storeQueue[storeWBIdx].inst);
}
}
if (dcacheInterface) {
assert(!req->completionEvent);
if (!dcachePort->sendTiming(data_pkt)) {
// Need to handle becoming blocked on a store.
} else {
/*
StoreCompletionEvent *store_event = new
StoreCompletionEvent(storeWBIdx, NULL, this);
req->completionEvent = store_event;
MemAccessResult result = dcacheInterface->access(req);
*/
if (isStalled() &&
storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
@ -619,19 +620,19 @@ LSQUnit<Impl>::writebackStores()
stallingStoreIsn = 0;
iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
}
typename IEW::LdWritebackEvent *wb = NULL;
/*
typename LdWritebackEvent *wb = NULL;
if (req->flags & LOCKED) {
// Stx_C should not generate a system port transaction
// if it misses in the cache, but that might be hard
// to accomplish without explicit cache support.
wb = new typename
IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
iewStage);
LdWritebackEvent(storeQueue[storeWBIdx].inst,
iewStage);
store_event->wbEvent = wb;
}
if (result != MA_HIT && dcacheInterface->doEvents()) {
*/
if (data_pkt->result != Packet::Success) {
DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
storeWBIdx);
@ -652,8 +653,6 @@ LSQUnit<Impl>::writebackStores()
}
incrStIdx(storeWBIdx);
} else {
panic("Must HAVE DCACHE!!!!!\n");
}
}
@ -747,12 +746,6 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
storeQueue[store_idx].inst = NULL;
storeQueue[store_idx].canWB = 0;
if (storeQueue[store_idx].req) {
// There should not be a completion event if the store has
// not yet committed.
assert(!storeQueue[store_idx].req->completionEvent);
}
storeQueue[store_idx].req = NULL;
--stores;

View file

@ -31,6 +31,7 @@
#include "arch/isa_traits.hh"
#include "arch/faults.hh"
#include "arch/types.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/o3/comm.hh"
@ -44,9 +45,8 @@
/**
* Simple physical register file class.
* This really only depends on the ISA, and not the Impl. Things that are
* in the ifdef FULL_SYSTEM are pretty dependent on the ISA, and probably
* should go in the AlphaFullCPU.
* Right now this is specific to Alpha until we decide if/how to make things
* generic enough to support other ISAs.
*/
template <class Impl>
class PhysRegFile
@ -54,8 +54,15 @@ class PhysRegFile
protected:
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscRegFile MiscRegFile;
typedef TheISA::MiscReg MiscReg;
typedef union {
FloatReg d;
FloatRegBits q;
} PhysFloatReg;
// Note that most of the definitions of the IntReg, FloatReg, etc. exist
// within the Impl/ISA class and not within this PhysRegFile class.
@ -97,7 +104,7 @@ class PhysRegFile
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
FloatReg floatReg = floatRegFile.readReg(reg_idx, width);
FloatReg floatReg = floatRegFile[reg_idx].d;
DPRINTF(IEW, "RegFile: Access to %d byte float register %i, has "
"data %8.8d\n", int(reg_idx), (double)floatReg);
@ -113,7 +120,7 @@ class PhysRegFile
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
FloatReg floatReg = floatRegFile.readReg(reg_idx);
FloatReg floatReg = floatRegFile[reg_idx].d;
DPRINTF(IEW, "RegFile: Access to float register %i, has "
"data %8.8d\n", int(reg_idx), (double)floatReg);
@ -129,7 +136,7 @@ class PhysRegFile
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx, width);
FloatRegBits floatRegBits = floatRegFile[reg_idx].q;
DPRINTF(IEW, "RegFile: Access to %d byte float register %i as int, "
"has data %lli\n", int(reg_idx), (uint64_t)floatRegBits);
@ -144,7 +151,7 @@ class PhysRegFile
assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx);
FloatRegBits floatRegBits = floatRegFile[reg_idx].q;
DPRINTF(IEW, "RegFile: Access to float register %i as int, "
"has data %lli\n", int(reg_idx), (uint64_t)floatRegBits);
@ -176,7 +183,7 @@ class PhysRegFile
int(reg_idx), (double)val);
if (reg_idx != TheISA::ZeroReg)
floatRegFile.setReg(reg_idx, val, width);
floatRegFile[reg_idx].d = width;
}
/** Sets a double precision floating point register to the given value. */
@ -191,7 +198,7 @@ class PhysRegFile
int(reg_idx), (double)val);
if (reg_idx != TheISA::ZeroReg)
floatRegFile.setReg(reg_idx, val);
floatRegFile[reg_idx].d = val;
}
/** Sets a floating point register to the given integer value. */
@ -205,7 +212,7 @@ class PhysRegFile
DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n",
int(reg_idx), (uint64_t)val);
floatRegFile.setRegBits(reg_idx, val, width);
floatRegFile[reg_idx].q = val;
}
void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val)
@ -217,6 +224,13 @@ class PhysRegFile
DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n",
int(reg_idx), (uint64_t)val);
floatRegFile[reg_idx].q = val;
}
MiscReg readMiscReg(int misc_reg, unsigned thread_id)
{
return miscRegs[thread_id].readReg(misc_reg);
}
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault,
@ -249,7 +263,7 @@ class PhysRegFile
std::vector<IntReg> intRegFile;
/** Floating point register file. */
std::vector<FloatReg> floatRegFile;
std::vector<PhysFloatReg> floatRegFile;
/** Miscellaneous register file. */
MiscRegFile miscRegs[Impl::MaxThreads];

View file

@ -29,6 +29,7 @@
#ifndef __CPU_O3_SAT_COUNTER_HH__
#define __CPU_O3_SAT_COUNTER_HH__
#include "base/misc.hh"
#include "sim/host.hh"
/**

View file

@ -77,7 +77,7 @@ struct O3ThreadState : public ThreadState {
{ }
#else
O3ThreadState(FullCPU *_cpu, int _thread_num, Process *_process, int _asid)
: ThreadState(-1, _thread_num, _process->getMemory(), _process, _asid),
: ThreadState(-1, _thread_num, NULL, _process, _asid),
cpu(_cpu), inSyscall(0), trapPending(0)
{ }
@ -96,14 +96,6 @@ struct O3ThreadState : public ThreadState {
void setStatus(Status new_status) { _status = new_status; }
#if !FULL_SYSTEM
bool validInstAddr(Addr addr)
{ return process->validInstAddr(addr); }
bool validDataAddr(Addr addr)
{ return process->validDataAddr(addr); }
#endif
bool misspeculating() { return false; }
void setInst(TheISA::MachInst _inst) { inst = _inst; }
@ -113,7 +105,7 @@ struct O3ThreadState : public ThreadState {
void setFuncExeInst(Counter new_val) { funcExeInst = new_val; }
#if !FULL_SYSTEM
void syscall() { process->syscall(xcProxy); }
void syscall(int64_t callnum) { process->syscall(callnum, xcProxy); }
#endif
};

View file

@ -59,6 +59,6 @@ enum OpClass {
/**
* Array mapping OpClass enum values to strings. Defined in op_class.cc.
*/
extern const char *opClassStrings[];
extern const char *opClassStrings[Num_OpClasses];
#endif // __CPU__OP_CLASS_HH__

View file

@ -11,9 +11,7 @@
#include "cpu/inst_seq.hh"
#include "cpu/ozone/rename_table.hh"
#include "cpu/ozone/thread_state.hh"
#include "mem/functional/functional.hh"
#include "mem/mem_interface.hh"
#include "mem/mem_req.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
class ExecContext;
@ -188,10 +186,10 @@ class BackEnd
bool xcSquash;
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx);
Fault read(RequestPtr req, T &data, int load_idx);
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx);
Fault write(RequestPtr req, T &data, int store_idx);
Addr readCommitPC() { return commitPC; }
@ -291,7 +289,7 @@ class BackEnd
MemInterface *dcacheInterface;
MemReqPtr memReq;
Request *memReq;
// General back end width. Used if the more specific isn't given.
int width;
@ -430,7 +428,7 @@ class BackEnd
template <class Impl>
template <class T>
Fault
BackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
BackEnd<Impl>::read(RequestPtr req, T &data, int load_idx)
{
/* memReq->reset(addr, sizeof(T), flags);
@ -475,7 +473,7 @@ BackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
template <class Impl>
template <class T>
Fault
BackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
BackEnd<Impl>::write(RequestPtr req, T &data, int store_idx)
{
/*
memReq->reset(addr, sizeof(T), flags);

View file

@ -41,7 +41,6 @@
#include "cpu/ozone/thread_state.hh"
#include "cpu/pc_event.hh"
#include "cpu/static_inst.hh"
#include "mem/mem_interface.hh"
#include "sim/eventq.hh"
// forward declarations
@ -69,7 +68,7 @@ class Process;
class Checkpoint;
class EndQuiesceEvent;
class MemInterface;
class Request;
namespace Trace {
class InstRecord;
@ -95,6 +94,8 @@ class OzoneCPU : public BaseCPU
typedef typename Impl::DynInst DynInst;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
public:
@ -110,7 +111,7 @@ class OzoneCPU : public BaseCPU
int readCpuId() { return thread->cpuId; }
FunctionalMemory *getMemPtr() { return thread->mem; }
TranslatingPort *getMemPort() { return /*thread->port*/NULL; }
#if FULL_SYSTEM
System *getSystemPtr() { return cpu->system; }
@ -175,19 +176,23 @@ class OzoneCPU : public BaseCPU
uint64_t readIntReg(int reg_idx);
float readFloatRegSingle(int reg_idx);
FloatReg readFloatReg(int reg_idx, int width);
double readFloatRegDouble(int reg_idx);
FloatReg readFloatReg(int reg_idx);
uint64_t readFloatRegInt(int reg_idx);
FloatRegBits readFloatRegBits(int reg_idx, int width);
FloatRegBits readFloatRegBits(int reg_idx);
void setIntReg(int reg_idx, uint64_t val);
void setFloatRegSingle(int reg_idx, float val);
void setFloatReg(int reg_idx, FloatReg val, int width);
void setFloatRegDouble(int reg_idx, double val);
void setFloatReg(int reg_idx, FloatReg val);
void setFloatRegInt(int reg_idx, uint64_t val);
void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
void setFloatRegBits(int reg_idx, FloatRegBits val);
uint64_t readPC() { return thread->PC; }
void setPC(Addr val);
@ -195,6 +200,15 @@ class OzoneCPU : public BaseCPU
uint64_t readNextPC() { return thread->nextPC; }
void setNextPC(Addr val);
uint64_t readNextNPC()
{
panic("Alpha has no NextNPC!");
return 0;
}
void setNextNPC(uint64_t val)
{ panic("Alpha has no NextNPC!"); }
public:
// ISA stuff:
MiscReg readMiscReg(int misc_reg);
@ -233,6 +247,9 @@ class OzoneCPU : public BaseCPU
void setFuncExeInst(Counter new_val)
{ thread->funcExeInst = new_val; }
#endif
void changeRegFileContext(TheISA::RegFile::ContextParam param,
TheISA::RegFile::ContextVal val)
{ panic("Not supported on Alpha!"); }
};
// execution context proxy
@ -350,10 +367,10 @@ class OzoneCPU : public BaseCPU
#endif
// L1 instruction cache
MemInterface *icacheInterface;
// MemInterface *icacheInterface;
// L1 data cache
MemInterface *dcacheInterface;
// MemInterface *dcacheInterface;
/** Pointer to memory. */
FunctionalMemory *mem;
@ -427,40 +444,28 @@ class OzoneCPU : public BaseCPU
int getInstAsid() { return thread.asid; }
int getDataAsid() { return thread.asid; }
Fault dummyTranslation(MemReqPtr &req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
#endif
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
return NoFault;
}
/** Translates instruction requestion in syscall emulation mode. */
Fault translateInstReq(MemReqPtr &req)
Fault translateInstReq(Request *req)
{
return dummyTranslation(req);
return thread.translateInstReq(req);
}
/** Translates data read request in syscall emulation mode. */
Fault translateDataReadReq(MemReqPtr &req)
Fault translateDataReadReq(Request *req)
{
return dummyTranslation(req);
return thread.translateDataReadReq(req);
}
/** Translates data write request in syscall emulation mode. */
Fault translateDataWriteReq(MemReqPtr &req)
Fault translateDataWriteReq(Request *req)
{
return dummyTranslation(req);
return thread.translateDataWriteReq(req);
}
#endif
/** Old CPU read from memory function. No longer used. */
template <class T>
Fault read(MemReqPtr &req, T &data)
Fault read(Request *req, T &data)
{
#if 0
#if FULL_SYSTEM && defined(TARGET_ALPHA)
@ -469,12 +474,12 @@ class OzoneCPU : public BaseCPU
req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
}
#endif
#endif
Fault error;
if (req->flags & LOCKED) {
lockAddrList.insert(req->paddr);
lockFlag = true;
}
#endif
Fault error;
error = this->mem->read(req, data);
data = gtoh(data);
@ -484,14 +489,14 @@ class OzoneCPU : public BaseCPU
/** CPU read function, forwards read to LSQ. */
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx)
Fault read(Request *req, T &data, int load_idx)
{
return backEnd->read(req, data, load_idx);
}
/** Old CPU write to memory function. No longer used. */
template <class T>
Fault write(MemReqPtr &req, T &data)
Fault write(Request *req, T &data)
{
#if 0
#if FULL_SYSTEM && defined(TARGET_ALPHA)
@ -539,7 +544,6 @@ class OzoneCPU : public BaseCPU
}
}
#endif
#endif
if (req->flags & LOCKED) {
@ -560,13 +564,14 @@ class OzoneCPU : public BaseCPU
}
}
}
#endif
return this->mem->write(req, (T)htog(data));
}
/** CPU write function, forwards write to LSQ. */
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx)
Fault write(Request *req, T &data, int store_idx)
{
return backEnd->write(req, data, store_idx);
}

View file

@ -920,23 +920,39 @@ OzoneCPU<Impl>::OzoneXC::readIntReg(int reg_idx)
template <class Impl>
float
OzoneCPU<Impl>::OzoneXC::readFloatRegSingle(int reg_idx)
OzoneCPU<Impl>::OzoneXC::readFloatReg(int reg_idx, int width)
{
int idx = reg_idx + TheISA::FP_Base_DepTag;
switch(width) {
case 32:
return thread->renameTable[idx]->readFloatResult();
case 64:
return thread->renameTable[idx]->readDoubleResult();
default:
panic("Unsupported width!");
return 0;
}
}
template <class Impl>
double
OzoneCPU<Impl>::OzoneXC::readFloatReg(int reg_idx)
{
int idx = reg_idx + TheISA::FP_Base_DepTag;
return thread->renameTable[idx]->readFloatResult();
}
template <class Impl>
double
OzoneCPU<Impl>::OzoneXC::readFloatRegDouble(int reg_idx)
uint64_t
OzoneCPU<Impl>::OzoneXC::readFloatRegBits(int reg_idx, int width)
{
int idx = reg_idx + TheISA::FP_Base_DepTag;
return thread->renameTable[idx]->readDoubleResult();
return thread->renameTable[idx]->readIntResult();
}
template <class Impl>
uint64_t
OzoneCPU<Impl>::OzoneXC::readFloatRegInt(int reg_idx)
OzoneCPU<Impl>::OzoneXC::readFloatRegBits(int reg_idx)
{
int idx = reg_idx + TheISA::FP_Base_DepTag;
return thread->renameTable[idx]->readIntResult();
@ -955,14 +971,28 @@ OzoneCPU<Impl>::OzoneXC::setIntReg(int reg_idx, uint64_t val)
template <class Impl>
void
OzoneCPU<Impl>::OzoneXC::setFloatRegSingle(int reg_idx, float val)
OzoneCPU<Impl>::OzoneXC::setFloatReg(int reg_idx, FloatReg val, int width)
{
panic("Unimplemented!");
int idx = reg_idx + TheISA::FP_Base_DepTag;
switch(width) {
case 32:
panic("Unimplemented!");
break;
case 64:
thread->renameTable[idx]->setDoubleResult(val);
break;
default:
panic("Unsupported width!");
}
if (!thread->inSyscall) {
cpu->squashFromXC();
}
}
template <class Impl>
void
OzoneCPU<Impl>::OzoneXC::setFloatRegDouble(int reg_idx, double val)
OzoneCPU<Impl>::OzoneXC::setFloatReg(int reg_idx, FloatReg val)
{
int idx = reg_idx + TheISA::FP_Base_DepTag;
@ -975,7 +1005,15 @@ OzoneCPU<Impl>::OzoneXC::setFloatRegDouble(int reg_idx, double val)
template <class Impl>
void
OzoneCPU<Impl>::OzoneXC::setFloatRegInt(int reg_idx, uint64_t val)
OzoneCPU<Impl>::OzoneXC::setFloatRegBits(int reg_idx, FloatRegBits val,
int width)
{
panic("Unimplemented!");
}
template <class Impl>
void
OzoneCPU<Impl>::OzoneXC::setFloatRegBits(int reg_idx, FloatRegBits val)
{
panic("Unimplemented!");
}

View file

@ -28,8 +28,8 @@
#include "cpu/ozone/dyn_inst_impl.hh"
#include "cpu/ozone/ozone_impl.hh"
#include "cpu/ozone/simple_impl.hh"
//#include "cpu/ozone/simple_impl.hh"
template class OzoneDynInst<OzoneImpl>;
template class OzoneDynInst<SimpleImpl>;
//template class OzoneDynInst<SimpleImpl>;

View file

@ -34,7 +34,7 @@
#include "cpu/base_dyn_inst.hh"
#include "cpu/ozone/cpu.hh" // MUST include this
#include "cpu/inst_seq.hh"
#include "cpu/ozone/simple_impl.hh" // Would be nice to not have to include this
//#include "cpu/ozone/simple_impl.hh" // Would be nice to not have to include this
#include "cpu/ozone/ozone_impl.hh"
#include <list>

View file

@ -34,7 +34,7 @@
#include "cpu/inst_seq.hh"
#include "cpu/o3/bpred_unit.hh"
#include "cpu/ozone/rename_table.hh"
#include "mem/mem_req.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
#include "sim/stats.hh"
@ -85,7 +85,7 @@ class FrontEnd
const bool is_branch = false, const bool branch_taken = false);
DynInstPtr getInst();
void processCacheCompletion(MemReqPtr &req);
void processCacheCompletion(Packet *pkt);
void addFreeRegs(int num_freed);
@ -159,26 +159,39 @@ class FrontEnd
BranchPred branchPred;
class ICacheCompletionEvent : public Event
class IcachePort : public Port
{
private:
MemReqPtr req;
FrontEnd *frontEnd;
protected:
FrontEnd *fe;
public:
ICacheCompletionEvent(MemReqPtr &_req, FrontEnd *_fe);
IcachePort(const std::string &_name, FrontEnd *_fe)
: Port(_name), fe(_fe)
{ }
virtual void process();
virtual const char *description();
protected:
virtual Tick recvAtomic(PacketPtr pkt);
virtual void recvFunctional(PacketPtr pkt);
virtual void recvStatusChange(Status status);
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
virtual bool recvTiming(PacketPtr pkt);
virtual void recvRetry();
};
MemInterface *icacheInterface;
IcachePort icachePort;
#if !FULL_SYSTEM
PageTable *pTable;
#endif
MemReqPtr memReq;
RequestPtr memReq;
/** Mask to get a cache block's address. */
Addr cacheBlkMask;

View file

@ -10,8 +10,7 @@
#include "cpu/inst_seq.hh"
#include "cpu/ozone/rename_table.hh"
#include "cpu/ozone/thread_state.hh"
#include "mem/mem_interface.hh"
#include "mem/mem_req.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
template <class Impl>
@ -85,13 +84,13 @@ class InorderBackEnd
Fault read(Addr addr, T &data, unsigned flags);
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx);
Fault read(RequestPtr req, T &data, int load_idx);
template <class T>
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx);
Fault write(RequestPtr req, T &data, int store_idx);
Addr readCommitPC() { return commitPC; }
@ -142,9 +141,9 @@ class InorderBackEnd
DCacheCompletionEvent cacheCompletionEvent;
MemInterface *dcacheInterface;
// MemInterface *dcacheInterface;
MemReqPtr memReq;
RequestPtr memReq;
private:
typedef typename std::list<DynInstPtr>::iterator InstListIt;

View file

@ -39,9 +39,7 @@
#include "cpu/inst_seq.hh"
#include "cpu/ozone/rename_table.hh"
#include "cpu/ozone/thread_state.hh"
#include "mem/functional/functional.hh"
#include "mem/mem_interface.hh"
#include "mem/mem_req.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
template <class>
@ -146,10 +144,10 @@ class LWBackEnd
bool xcSquash;
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx);
Fault read(RequestPtr req, T &data, int load_idx);
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx);
Fault write(RequestPtr req, T &data, int store_idx);
Addr readCommitPC() { return commitPC; }
@ -291,8 +289,6 @@ class LWBackEnd
MemInterface *dcacheInterface;
MemReqPtr memReq;
// General back end width. Used if the more specific isn't given.
int width;
@ -457,7 +453,7 @@ class LWBackEnd
template <class Impl>
template <class T>
Fault
LWBackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
LWBackEnd<Impl>::read(RequestPtr req, T &data, int load_idx)
{
return LSQ.read(req, data, load_idx);
}
@ -465,7 +461,7 @@ LWBackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
template <class Impl>
template <class T>
Fault
LWBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
LWBackEnd<Impl>::write(RequestPtr req, T &data, int store_idx)
{
return LSQ.write(req, data, store_idx);
}

View file

@ -39,7 +39,8 @@
#include "config/full_system.hh"
#include "base/hashmap.hh"
#include "cpu/inst_seq.hh"
#include "mem/mem_interface.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
//#include "mem/page_table.hh"
#include "sim/debug.hh"
#include "sim/sim_object.hh"
@ -228,8 +229,8 @@ class OzoneLWLSQ {
/** Returns if the LSQ unit will writeback on this cycle. */
bool willWB() { return storeQueue.back().canWB &&
!storeQueue.back().completed &&
!dcacheInterface->isBlocked(); }
!storeQueue.back().completed/* &&
!dcacheInterface->isBlocked()*/; }
void switchOut();
@ -250,8 +251,36 @@ class OzoneLWLSQ {
/** Pointer to the back-end stage. */
BackEnd *be;
MemObject *mem;
class DcachePort : public Port
{
protected:
FullCPU *cpu;
public:
DcachePort(const std::string &_name, FullCPU *_cpu)
: Port(_name), cpu(_cpu)
{ }
protected:
virtual Tick recvAtomic(PacketPtr pkt);
virtual void recvFunctional(PacketPtr pkt);
virtual void recvStatusChange(Status status);
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
virtual bool recvTiming(PacketPtr pkt);
virtual void recvRetry();
};
/** Pointer to the D-cache. */
MemInterface *dcacheInterface;
DcachePort dcachePort;
/** Pointer to the page table. */
// PageTable *pTable;
@ -273,7 +302,7 @@ class OzoneLWLSQ {
/** The store instruction. */
DynInstPtr inst;
/** The memory request for the store. */
MemReqPtr req;
RequestPtr req;
/** The size of the store. */
int size;
/** The store data. */
@ -388,11 +417,11 @@ class OzoneLWLSQ {
public:
/** Executes the load at the given index. */
template <class T>
Fault read(MemReqPtr &req, T &data, int load_idx);
Fault read(RequestPtr req, T &data, int load_idx);
/** Executes the store at the given index. */
template <class T>
Fault write(MemReqPtr &req, T &data, int store_idx);
Fault write(RequestPtr req, T &data, int store_idx);
/** Returns the sequence number of the head load instruction. */
InstSeqNum getLoadHeadSeqNum()
@ -423,7 +452,7 @@ class OzoneLWLSQ {
template <class Impl>
template <class T>
Fault
OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
{
//Depending on issue2execute delay a squashed load could
//execute if it is found to be squashed in the same
@ -433,20 +462,12 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
assert(lq_hash_it != LQItHash.end());
DynInstPtr inst = (*(*lq_hash_it).second);
if (inst->isExecuted()) {
panic("Should not reach this point with split ops!");
memcpy(&data,req->data,req->size);
return NoFault;
}
// Make sure this isn't an uncacheable access
// A bit of a hackish way to get uncached accesses to work only if they're
// at the head of the LSQ and are ready to commit (at the head of the ROB
// too).
// @todo: Fix uncached accesses.
if (req->flags & UNCACHEABLE &&
if (req->getFlags() & UNCACHEABLE &&
(inst != loadQueue.back() || !inst->reachedCommit)) {
DPRINTF(OzoneLSQ, "[sn:%lli] Uncached load and not head of "
"commit/LSQ!\n",
@ -460,7 +481,7 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
int store_size = 0;
DPRINTF(OzoneLSQ, "Read called, load idx: %i addr: %#x\n",
load_idx, req->paddr);
load_idx, req->getPaddr());
while (sq_it != storeQueue.end() && (*sq_it).inst->seqNum > inst->seqNum)
++sq_it;
@ -483,39 +504,34 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
// Check if the store data is within the lower and upper bounds of
// addresses that the request needs.
bool store_has_lower_limit =
req->vaddr >= (*sq_it).inst->effAddr;
req->getVaddr() >= (*sq_it).inst->effAddr;
bool store_has_upper_limit =
(req->vaddr + req->size) <= ((*sq_it).inst->effAddr +
store_size);
(req->getVaddr() + req->getSize()) <= ((*sq_it).inst->effAddr +
store_size);
bool lower_load_has_store_part =
req->vaddr < ((*sq_it).inst->effAddr +
store_size);
req->getVaddr() < ((*sq_it).inst->effAddr +
store_size);
bool upper_load_has_store_part =
(req->vaddr + req->size) > (*sq_it).inst->effAddr;
(req->getVaddr() + req->getSize()) > (*sq_it).inst->effAddr;
// If the store's data has all of the data needed, we can forward.
if (store_has_lower_limit && store_has_upper_limit) {
int shift_amt = req->vaddr & (store_size - 1);
int shift_amt = req->getVaddr() & (store_size - 1);
// Assumes byte addressing
shift_amt = shift_amt << 3;
// Cast this to type T?
data = (*sq_it).data >> shift_amt;
req->cmd = Read;
assert(!req->completionEvent);
req->completionEvent = NULL;
req->time = curTick;
assert(!req->data);
req->data = new uint8_t[64];
assert(!inst->memData);
inst->memData = new uint8_t[64];
memcpy(req->data, &data, req->size);
memcpy(inst->memData, &data, req->getSize());
DPRINTF(OzoneLSQ, "Forwarding from store [sn:%lli] to load to "
"[sn:%lli] addr %#x, data %#x\n",
(*sq_it).inst->seqNum, inst->seqNum, req->vaddr, *(req->data));
(*sq_it).inst->seqNum, inst->seqNum, req->vaddr, *(inst->memData));
/*
typename BackEnd::LdWritebackEvent *wb =
new typename BackEnd::LdWritebackEvent(inst,
be);
@ -524,7 +540,7 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
// for now.
// FIXME - Need to make this a parameter.
wb->schedule(curTick);
*/
// Should keep track of stat for forwarded data
return NoFault;
} else if ((store_has_lower_limit && lower_load_has_store_part) ||
@ -568,60 +584,41 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
DPRINTF(OzoneLSQ, "Doing functional access for inst PC %#x\n",
inst->readPC());
// Setup MemReq pointer
req->cmd = Read;
req->completionEvent = NULL;
req->time = curTick;
assert(!req->data);
req->data = new uint8_t[64];
Fault fault = cpu->read(req, data);
memcpy(req->data, &data, sizeof(T));
assert(!inst->memData);
inst->memData = new uint8_t[64];
++usedPorts;
DPRINTF(OzoneLSQ, "Doing timing access for inst PC %#x\n",
inst->readPC());
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(inst->memData);
// if we have a cache, do cache access too
if (dcacheInterface) {
if (dcacheInterface->isBlocked()) {
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
return NoFault;
isLoadBlocked = true;
loadBlockedHandled = false;
blockedLoadSeqNum = inst->seqNum;
// No fault occurred, even though the interface is blocked.
if (!dcachePort.sendTiming(data_pkt)) {
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
return NoFault;
}
DPRINTF(OzoneLSQ, "D-cache: PC:%#x reading from paddr:%#x "
"vaddr:%#x flags:%i\n",
inst->readPC(), req->paddr, req->vaddr, req->flags);
// Record that the load was blocked due to memory. This
// load will squash all instructions after it, be
// refetched, and re-executed.
isLoadBlocked = true;
loadBlockedHandled = false;
blockedLoadSeqNum = inst->seqNum;
// No fault occurred, even though the interface is blocked.
return NoFault;
}
assert(!req->completionEvent);
req->completionEvent =
new typename BackEnd::LdWritebackEvent(inst, be);
// Do Cache Access
MemAccessResult result = dcacheInterface->access(req);
// 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.
// @todo: Probably should support having no events
if (result != MA_HIT) {
DPRINTF(OzoneLSQ, "D-cache miss!\n");
DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
inst->seqNum);
lastDcacheStall = curTick;
_status = DcacheMissStall;
} else {
DPRINTF(OzoneLSQ, "D-cache hit!\n");
}
if (data_pkt->result != Packet::Success) {
DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache miss!\n");
DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
inst->seqNum);
} else {
fatal("Must use D-cache with new memory system");
DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache hit!\n");
DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
inst->seqNum);
}
return NoFault;
@ -630,7 +627,7 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
template <class Impl>
template <class T>
Fault
OzoneLWLSQ<Impl>::write(MemReqPtr &req, T &data, int store_idx)
OzoneLWLSQ<Impl>::write(RequestPtr req, T &data, int store_idx)
{
SQHashIt sq_hash_it = SQItHash.find(store_idx);
assert(sq_hash_it != SQItHash.end());
@ -640,14 +637,16 @@ OzoneLWLSQ<Impl>::write(MemReqPtr &req, T &data, int store_idx)
DPRINTF(OzoneLSQ, "Doing write to store idx %i, addr %#x data %#x"
" | [sn:%lli]\n",
store_idx, req->paddr, data, (*sq_it).inst->seqNum);
store_idx, req->getPaddr(), data, (*sq_it).inst->seqNum);
(*sq_it).req = req;
(*sq_it).size = sizeof(T);
(*sq_it).data = data;
/*
assert(!req->data);
req->data = new uint8_t[64];
memcpy(req->data, (uint8_t *)&(*sq_it).data, req->size);
*/
// This function only writes the data to the store queue, so no fault
// can happen here.

View file

@ -31,10 +31,8 @@
#include "arch/alpha/isa_traits.hh"
#include "cpu/o3/bpred_unit.hh"
#include "cpu/ozone/back_end.hh"
#include "cpu/ozone/front_end.hh"
#include "cpu/ozone/inst_queue.hh"
#include "cpu/ozone/lsq_unit.hh"
#include "cpu/ozone/lw_lsq.hh"
#include "cpu/ozone/lw_back_end.hh"
#include "cpu/ozone/null_predictor.hh"

View file

@ -68,7 +68,7 @@ struct OzoneThreadState : public ThreadState {
}
#else
OzoneThreadState(FullCPU *_cpu, int _thread_num, Process *_process, int _asid)
: ThreadState(-1, _thread_num, _process->getMemory(), _process, _asid),
: ThreadState(-1, _thread_num, NULL, _process, _asid),
cpu(_cpu), inSyscall(0), trapPending(0)
{
memset(&regs, 0, sizeof(TheISA::RegFile));
@ -109,42 +109,30 @@ struct OzoneThreadState : public ThreadState {
ExecContext *getXCProxy() { return xcProxy; }
#if !FULL_SYSTEM
Fault dummyTranslation(MemReqPtr &req)
Fault translateInstReq(Request *req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
#endif
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
return NoFault;
return process->pTable->translate(req);
}
Fault translateInstReq(MemReqPtr &req)
Fault translateDataReadReq(Request *req)
{
return dummyTranslation(req);
return process->pTable->translate(req);
}
Fault translateDataReadReq(MemReqPtr &req)
Fault translateDataWriteReq(Request *req)
{
return dummyTranslation(req);
}
Fault translateDataWriteReq(MemReqPtr &req)
{
return dummyTranslation(req);
return process->pTable->translate(req);
}
#else
Fault translateInstReq(MemReqPtr &req)
Fault translateInstReq(Request *req)
{
return cpu->itb->translate(req);
}
Fault translateDataReadReq(MemReqPtr &req)
Fault translateDataReadReq(Request *req)
{
return cpu->dtb->translate(req, false);
}
Fault translateDataWriteReq(MemReqPtr &req)
Fault translateDataWriteReq(Request *req)
{
return cpu->dtb->translate(req, true);
}
@ -152,22 +140,22 @@ struct OzoneThreadState : public ThreadState {
MiscReg readMiscReg(int misc_reg)
{
return regs.miscRegs.readReg(misc_reg);
return regs.readMiscReg(misc_reg);
}
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
{
return regs.miscRegs.readRegWithEffect(misc_reg, fault, xcProxy);
return regs.readMiscRegWithEffect(misc_reg, fault, xcProxy);
}
Fault setMiscReg(int misc_reg, const MiscReg &val)
{
return regs.miscRegs.setReg(misc_reg, val);
return regs.setMiscReg(misc_reg, val);
}
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
{
return regs.miscRegs.setRegWithEffect(misc_reg, val, xcProxy);
return regs.setMiscRegWithEffect(misc_reg, val, xcProxy);
}
uint64_t readPC()

View file

@ -124,6 +124,13 @@ class Request
: validCpuAndThreadNums(false)
{ setPhys(_paddr, _size, _flags); }
Request(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc,
int _cpuNum, int _threadNum)
{
setThreadContext(_cpuNum, _threadNum);
setVirt(_asid, _vaddr, _size, _flags, _pc);
}
/**
* Set up CPU and thread numbers. */
void setThreadContext(int _cpuNum, int _threadNum)