CPU: Add functions to the "ExecContext"s that translate a given address.

--HG--
extra : convert_revision : 7d898c6b6b13094fd05326eaa0b095a3ab132397
This commit is contained in:
Gabe Black
2007-10-22 14:30:45 -07:00
parent 43cb78004b
commit 93da9eb7f6
5 changed files with 216 additions and 0 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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__

View File

@@ -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

View File

@@ -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 );