CPU: Add functions to the "ExecContext"s that translate a given address.
authorGabe Black <gblack@eecs.umich.edu>
Mon, 22 Oct 2007 21:30:45 +0000 (14:30 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 22 Oct 2007 21:30:45 +0000 (14:30 -0700)
--HG--
extra : convert_revision : 7d898c6b6b13094fd05326eaa0b095a3ab132397

src/cpu/base_dyn_inst.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/timing.cc
src/cpu/simple/timing.hh

index 0f2a90bf60683c91a454b9ef5484b33aaeaea2a9..74b250207c24d88d612d965a2c0658d56b83d5ed 100644 (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
index 9f574e8beeaf362b901e16e5ced7ee5d02d423d2..4e52f9b335a4991d89c2b2e41ff779f12d117328 100644 (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
 
index 96429e5b108a30fc412cc64e704bc402e526c872..f68f41a90d5e3d0ae8918d56cb3c574cdd77837d 100644 (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__
index f1e51ac7062064160cce881cfe8250af690ebc25..998d0b0171e5d13cd957c8aaf71f77d1e189ef41 100644 (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
index 668b6ddaf5257b7691f8ad95caad62726d16aa9c..d7554f6de6ec001276cbd2600d7ed37fb48e76da 100644 (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 );