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:
parent
d4b73086b6
commit
7940c10ace
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
]
|
||||
|
||||
#
|
||||
|
|
|
@ -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
|
||||
''')
|
||||
|
||||
|
|
|
@ -229,7 +229,6 @@ BaseCPU::registerExecContexts()
|
|||
#else
|
||||
xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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> > >;
|
|
@ -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;
|
|
@ -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__
|
|
@ -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;
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
|
||||
#include "base/intmath.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/o3/2bit_local_pred.hh"
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
// For Addr type.
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "base/misc.hh"
|
||||
|
||||
class DefaultBTB
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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];
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#ifndef __CPU_O3_SAT_COUNTER_HH__
|
||||
#define __CPU_O3_SAT_COUNTER_HH__
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "sim/host.hh"
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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__
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
@ -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>
|
|
@ -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;
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
|
@ -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"
|
|
@ -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(®s, 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()
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue