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.
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);
{ 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
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
}
}
+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
}
}
+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
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__
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
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
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 );