CPU: Add functions to the "ExecContext"s that translate a given address.
--HG-- extra : convert_revision : 7d898c6b6b13094fd05326eaa0b095a3ab132397
This commit is contained in:
@@ -102,6 +102,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||
template <class T>
|
||||
Fault read(Addr addr, T &data, unsigned flags);
|
||||
|
||||
Fault translateDataReadAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags);
|
||||
|
||||
/**
|
||||
* Does a write to a given address.
|
||||
* @param data The data to be written.
|
||||
@@ -114,6 +117,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||
Fault write(T data, Addr addr, unsigned flags,
|
||||
uint64_t *res);
|
||||
|
||||
Fault translateDataWriteAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags);
|
||||
|
||||
void prefetch(Addr addr, unsigned flags);
|
||||
void writeHint(Addr addr, int size, unsigned flags);
|
||||
Fault copySrcTranslate(Addr src);
|
||||
@@ -837,6 +843,29 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||
{ thread->storeCondFailures = sc_failures; }
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
Fault
|
||||
BaseDynInst<Impl>::translateDataReadAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags)
|
||||
{
|
||||
if (traceData) {
|
||||
traceData->setAddr(vaddr);
|
||||
}
|
||||
|
||||
reqMade = true;
|
||||
Request *req = new Request();
|
||||
req->setVirt(asid, vaddr, size, flags, PC);
|
||||
req->setThreadContext(thread->readCpuId(), threadNumber);
|
||||
|
||||
fault = cpu->translateDataReadReq(req, thread);
|
||||
|
||||
if (fault == NoFault)
|
||||
paddr = req->getPaddr();
|
||||
|
||||
delete req;
|
||||
return fault;
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
template<class T>
|
||||
inline Fault
|
||||
@@ -888,6 +917,29 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||
return fault;
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
Fault
|
||||
BaseDynInst<Impl>::translateDataWriteAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags)
|
||||
{
|
||||
if (traceData) {
|
||||
traceData->setAddr(vaddr);
|
||||
}
|
||||
|
||||
reqMade = true;
|
||||
Request *req = new Request();
|
||||
req->setVirt(asid, vaddr, size, flags, PC);
|
||||
req->setThreadContext(thread->readCpuId(), threadNumber);
|
||||
|
||||
fault = cpu->translateDataWriteReq(req, thread);
|
||||
|
||||
if (fault == NoFault)
|
||||
paddr = req->getPaddr();
|
||||
|
||||
delete req;
|
||||
return fault;
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
template<class T>
|
||||
inline Fault
|
||||
|
||||
@@ -366,6 +366,61 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
AtomicSimpleCPU::translateDataReadAddr(Addr vaddr, Addr & paddr,
|
||||
int size, unsigned flags)
|
||||
{
|
||||
// use the CPU's statically allocated read request and packet objects
|
||||
Request *req = &data_read_req;
|
||||
|
||||
if (traceData) {
|
||||
traceData->setAddr(vaddr);
|
||||
}
|
||||
|
||||
//The block size of our peer.
|
||||
int blockSize = dcachePort.peerBlockSize();
|
||||
//The size of the data we're trying to read.
|
||||
int dataSize = size;
|
||||
|
||||
bool firstTimeThrough = true;
|
||||
|
||||
//The address of the second part of this access if it needs to be split
|
||||
//across a cache line boundary.
|
||||
Addr secondAddr = roundDown(vaddr + dataSize - 1, blockSize);
|
||||
|
||||
if(secondAddr > vaddr)
|
||||
dataSize = secondAddr - vaddr;
|
||||
|
||||
while(1) {
|
||||
req->setVirt(0, vaddr, dataSize, flags, thread->readPC());
|
||||
|
||||
// translate to physical address
|
||||
Fault fault = thread->translateDataReadReq(req);
|
||||
|
||||
//If there's a fault, return it
|
||||
if (fault != NoFault)
|
||||
return fault;
|
||||
|
||||
if (firstTimeThrough) {
|
||||
paddr = req->getPaddr();
|
||||
firstTimeThrough = false;
|
||||
}
|
||||
|
||||
//If we don't need to access a second cache line, stop now.
|
||||
if (secondAddr <= vaddr)
|
||||
return fault;
|
||||
|
||||
/*
|
||||
* Set up for accessing the second cache line.
|
||||
*/
|
||||
|
||||
//Adjust the size to get the remaining bytes.
|
||||
dataSize = vaddr + size - secondAddr;
|
||||
//And access the right address.
|
||||
vaddr = secondAddr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
template
|
||||
@@ -524,6 +579,64 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
AtomicSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags)
|
||||
{
|
||||
// use the CPU's statically allocated write request and packet objects
|
||||
Request *req = &data_write_req;
|
||||
|
||||
if (traceData) {
|
||||
traceData->setAddr(vaddr);
|
||||
}
|
||||
|
||||
//The block size of our peer.
|
||||
int blockSize = dcachePort.peerBlockSize();
|
||||
|
||||
//The address of the second part of this access if it needs to be split
|
||||
//across a cache line boundary.
|
||||
Addr secondAddr = roundDown(vaddr + size - 1, blockSize);
|
||||
|
||||
//The size of the data we're trying to read.
|
||||
int dataSize = size;
|
||||
|
||||
bool firstTimeThrough = true;
|
||||
|
||||
if(secondAddr > vaddr)
|
||||
dataSize = secondAddr - vaddr;
|
||||
|
||||
dcache_latency = 0;
|
||||
|
||||
while(1) {
|
||||
req->setVirt(0, vaddr, flags, flags, thread->readPC());
|
||||
|
||||
// translate to physical address
|
||||
Fault fault = thread->translateDataWriteReq(req);
|
||||
|
||||
//If there's a fault or we don't need to access a second cache line,
|
||||
//stop now.
|
||||
if (fault != NoFault)
|
||||
return fault;
|
||||
|
||||
if (firstTimeThrough) {
|
||||
paddr = req->getPaddr();
|
||||
firstTimeThrough = false;
|
||||
}
|
||||
|
||||
if (secondAddr <= vaddr)
|
||||
return fault;
|
||||
|
||||
/*
|
||||
* Set up for accessing the second cache line.
|
||||
*/
|
||||
|
||||
//Adjust the size to get the remaining bytes.
|
||||
dataSize = vaddr + size - secondAddr;
|
||||
//And access the right address.
|
||||
vaddr = secondAddr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
|
||||
@@ -151,6 +151,11 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||
|
||||
template <class T>
|
||||
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
||||
|
||||
Fault translateDataReadAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags);
|
||||
Fault translateDataWriteAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags);
|
||||
};
|
||||
|
||||
#endif // __CPU_SIMPLE_ATOMIC_HH__
|
||||
|
||||
@@ -293,6 +293,26 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||
return fault;
|
||||
}
|
||||
|
||||
Fault
|
||||
TimingSimpleCPU::translateDataReadAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags)
|
||||
{
|
||||
Request *req =
|
||||
new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0);
|
||||
|
||||
if (traceData) {
|
||||
traceData->setAddr(vaddr);
|
||||
}
|
||||
|
||||
Fault fault = thread->translateDataWriteReq(req);
|
||||
|
||||
if (fault == NoFault)
|
||||
paddr = req->getPaddr();
|
||||
|
||||
delete req;
|
||||
return fault;
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
template
|
||||
@@ -411,6 +431,26 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||
return fault;
|
||||
}
|
||||
|
||||
Fault
|
||||
TimingSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags)
|
||||
{
|
||||
Request *req =
|
||||
new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0);
|
||||
|
||||
if (traceData) {
|
||||
traceData->setAddr(vaddr);
|
||||
}
|
||||
|
||||
Fault fault = thread->translateDataWriteReq(req);
|
||||
|
||||
if (fault == NoFault)
|
||||
paddr = req->getPaddr();
|
||||
|
||||
delete req;
|
||||
return fault;
|
||||
}
|
||||
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
template
|
||||
|
||||
@@ -189,9 +189,15 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||
template <class T>
|
||||
Fault read(Addr addr, T &data, unsigned flags);
|
||||
|
||||
Fault translateDataReadAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags);
|
||||
|
||||
template <class T>
|
||||
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
||||
|
||||
Fault translateDataWriteAddr(Addr vaddr, Addr &paddr,
|
||||
int size, unsigned flags);
|
||||
|
||||
void fetch();
|
||||
void completeIfetch(PacketPtr );
|
||||
void completeDataAccess(PacketPtr );
|
||||
|
||||
Reference in New Issue
Block a user