CPU: Add readBytes and writeBytes functions to the exec contexts.
This commit is contained in:
parent
65dbcc6ea1
commit
aa8c6e9c95
15 changed files with 253 additions and 366 deletions
|
@ -120,6 +120,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault read(Addr addr, T &data, unsigned flags);
|
Fault read(Addr addr, T &data, unsigned flags);
|
||||||
|
|
||||||
|
Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does a write to a given address.
|
* Does a write to a given address.
|
||||||
* @param data The data to be written.
|
* @param data The data to be written.
|
||||||
|
@ -131,6 +133,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
|
Fault writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
/** Splits a request in two if it crosses a dcache block. */
|
/** Splits a request in two if it crosses a dcache block. */
|
||||||
void splitRequest(RequestPtr req, RequestPtr &sreqLow,
|
void splitRequest(RequestPtr req, RequestPtr &sreqLow,
|
||||||
RequestPtr &sreqHigh);
|
RequestPtr &sreqHigh);
|
||||||
|
@ -867,12 +872,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
template<class T>
|
Fault
|
||||||
inline Fault
|
BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data,
|
||||||
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
unsigned size, unsigned flags)
|
||||||
{
|
{
|
||||||
reqMade = true;
|
reqMade = true;
|
||||||
Request *req = new Request(asid, addr, sizeof(T), flags, this->PC,
|
Request *req = new Request(asid, addr, size, flags, this->PC,
|
||||||
thread->contextId(), threadNumber);
|
thread->contextId(), threadNumber);
|
||||||
|
|
||||||
Request *sreqLow = NULL;
|
Request *sreqLow = NULL;
|
||||||
|
@ -889,11 +894,6 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||||
effAddrValid = true;
|
effAddrValid = true;
|
||||||
fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
|
fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Return a fixed value to keep simulation deterministic even
|
|
||||||
// along misspeculated paths.
|
|
||||||
data = (T)-1;
|
|
||||||
|
|
||||||
// Commit will have to clean up whatever happened. Set this
|
// Commit will have to clean up whatever happened. Set this
|
||||||
// instruction as executed.
|
// instruction as executed.
|
||||||
this->setExecuted();
|
this->setExecuted();
|
||||||
|
@ -901,7 +901,6 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
traceData->setAddr(addr);
|
traceData->setAddr(addr);
|
||||||
traceData->setData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fault;
|
return fault;
|
||||||
|
@ -910,15 +909,35 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
template<class T>
|
template<class T>
|
||||||
inline Fault
|
inline Fault
|
||||||
BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||||
{
|
{
|
||||||
|
Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
|
||||||
|
|
||||||
|
if (fault != NoFault) {
|
||||||
|
// Return a fixed value to keep simulation deterministic even
|
||||||
|
// along misspeculated paths.
|
||||||
|
data = (T)-1;
|
||||||
|
}
|
||||||
|
data = TheISA::gtoh(data);
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
traceData->setAddr(addr);
|
|
||||||
traceData->setData(data);
|
traceData->setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Impl>
|
||||||
|
Fault
|
||||||
|
BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
{
|
||||||
|
if (traceData) {
|
||||||
|
traceData->setAddr(addr);
|
||||||
|
}
|
||||||
|
|
||||||
reqMade = true;
|
reqMade = true;
|
||||||
Request *req = new Request(asid, addr, sizeof(T), flags, this->PC,
|
Request *req = new Request(asid, addr, size, flags, this->PC,
|
||||||
thread->contextId(), threadNumber);
|
thread->contextId(), threadNumber);
|
||||||
|
|
||||||
Request *sreqLow = NULL;
|
Request *sreqLow = NULL;
|
||||||
|
@ -939,6 +958,18 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
return fault;
|
return fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Impl>
|
||||||
|
template<class T>
|
||||||
|
inline Fault
|
||||||
|
BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
{
|
||||||
|
if (traceData) {
|
||||||
|
traceData->setData(data);
|
||||||
|
}
|
||||||
|
data = TheISA::htog(data);
|
||||||
|
return writeBytes((uint8_t *)&data, sizeof(T), addr, flags, res);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
inline void
|
inline void
|
||||||
BaseDynInst<Impl>::splitRequest(RequestPtr req, RequestPtr &sreqLow,
|
BaseDynInst<Impl>::splitRequest(RequestPtr req, RequestPtr &sreqLow,
|
||||||
|
|
|
@ -111,12 +111,17 @@ class ExecContext {
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault read(Addr addr, T &data, unsigned flags);
|
Fault read(Addr addr, T &data, unsigned flags);
|
||||||
|
|
||||||
|
Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
/** Writes to an address, creating a memory request with the given
|
/** Writes to an address, creating a memory request with the given
|
||||||
* flags. Writes data to memory. For store conditionals, returns
|
* flags. Writes data to memory. For store conditionals, returns
|
||||||
* the result of the store in res. */
|
* the result of the store in res. */
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
|
Fault writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
/** Prefetches an address, creating a memory request with the
|
/** Prefetches an address, creating a memory request with the
|
||||||
* given flags. */
|
* given flags. */
|
||||||
void prefetch(Addr addr, unsigned flags);
|
void prefetch(Addr addr, unsigned flags);
|
||||||
|
|
|
@ -1518,135 +1518,25 @@ InOrderCPU::getDTBPtr()
|
||||||
return dtb_res->tlb();
|
return dtb_res->tlb();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
InOrderCPU::read(DynInstPtr inst, Addr addr,
|
||||||
|
uint8_t *data, unsigned size, unsigned flags)
|
||||||
{
|
{
|
||||||
//@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
|
//@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
|
||||||
// you want to run w/out caches?
|
// you want to run w/out caches?
|
||||||
CacheUnit *cache_res =
|
CacheUnit *cache_res =
|
||||||
dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
|
dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
|
||||||
|
|
||||||
return cache_res->read(inst, addr, data, flags);
|
return cache_res->read(inst, addr, data, size, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
Fault
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags);
|
InOrderCPU::write(DynInstPtr inst, uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *write_res)
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, Twin64_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, uint64_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, uint32_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, uint16_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, uint8_t &data, unsigned flags);
|
|
||||||
|
|
||||||
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, double &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(inst, addr, *(uint64_t*)&data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, float &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(inst, addr, *(uint32_t*)&data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
InOrderCPU::read(DynInstPtr inst, Addr addr, int32_t &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(inst, addr, (uint32_t&)data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
|
||||||
uint64_t *write_res)
|
|
||||||
{
|
{
|
||||||
//@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
|
//@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
|
||||||
// you want to run w/out caches?
|
// you want to run w/out caches?
|
||||||
CacheUnit *cache_res =
|
CacheUnit *cache_res =
|
||||||
dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
|
dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
|
||||||
return cache_res->write(inst, data, addr, flags, write_res);
|
return cache_res->write(inst, data, size, addr, flags, write_res);
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, Twin32_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, Twin64_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, uint64_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, uint32_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, uint16_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, uint8_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, double data, Addr addr, unsigned flags,
|
|
||||||
uint64_t *res)
|
|
||||||
{
|
|
||||||
return write(inst, *(uint64_t*)&data, addr, flags, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, float data, Addr addr, unsigned flags,
|
|
||||||
uint64_t *res)
|
|
||||||
{
|
|
||||||
return write(inst, *(uint32_t*)&data, addr, flags, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
InOrderCPU::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags,
|
|
||||||
uint64_t *res)
|
|
||||||
{
|
|
||||||
return write(inst, (uint32_t)data, addr, flags, res);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -523,15 +523,14 @@ class InOrderCPU : public BaseCPU
|
||||||
/** Forwards an instruction read to the appropriate data
|
/** Forwards an instruction read to the appropriate data
|
||||||
* resource (indexes into Resource Pool thru "dataPortIdx")
|
* resource (indexes into Resource Pool thru "dataPortIdx")
|
||||||
*/
|
*/
|
||||||
template <class T>
|
Fault read(DynInstPtr inst, Addr addr,
|
||||||
Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
|
uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
/** Forwards an instruction write. to the appropriate data
|
/** Forwards an instruction write. to the appropriate data
|
||||||
* resource (indexes into Resource Pool thru "dataPortIdx")
|
* resource (indexes into Resource Pool thru "dataPortIdx")
|
||||||
*/
|
*/
|
||||||
template <class T>
|
Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
|
||||||
Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
Addr addr, unsigned flags, uint64_t *write_res = NULL);
|
||||||
uint64_t *write_res = NULL);
|
|
||||||
|
|
||||||
/** Forwards an instruction prefetch to the appropriate data
|
/** Forwards an instruction prefetch to the appropriate data
|
||||||
* resource (indexes into Resource Pool thru "dataPortIdx")
|
* resource (indexes into Resource Pool thru "dataPortIdx")
|
||||||
|
|
|
@ -610,6 +610,13 @@ InOrderDynInst::deallocateContext(int thread_num)
|
||||||
this->cpu->deallocateContext(thread_num);
|
this->cpu->deallocateContext(thread_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fault
|
||||||
|
InOrderDynInst::readBytes(Addr addr, uint8_t *data,
|
||||||
|
unsigned size, unsigned flags)
|
||||||
|
{
|
||||||
|
return cpu->read(this, addr, data, size, flags);
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline Fault
|
inline Fault
|
||||||
InOrderDynInst::read(Addr addr, T &data, unsigned flags)
|
InOrderDynInst::read(Addr addr, T &data, unsigned flags)
|
||||||
|
@ -618,8 +625,11 @@ InOrderDynInst::read(Addr addr, T &data, unsigned flags)
|
||||||
traceData->setAddr(addr);
|
traceData->setAddr(addr);
|
||||||
traceData->setData(data);
|
traceData->setData(data);
|
||||||
}
|
}
|
||||||
|
Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
|
||||||
return cpu->read(this, addr, data, flags);
|
data = TheISA::gtoh(data);
|
||||||
|
if (traceData)
|
||||||
|
traceData->setData(data);
|
||||||
|
return fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
@ -663,20 +673,29 @@ InOrderDynInst::read(Addr addr, int32_t &data, unsigned flags)
|
||||||
return read(addr, (uint32_t&)data, flags);
|
return read(addr, (uint32_t&)data, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fault
|
||||||
|
InOrderDynInst::writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
{
|
||||||
|
assert(sizeof(storeData) >= size);
|
||||||
|
memcpy(&storeData, data, size);
|
||||||
|
return cpu->write(this, (uint8_t *)&storeData, size, addr, flags, res);
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline Fault
|
inline Fault
|
||||||
InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
{
|
{
|
||||||
if (traceData) {
|
|
||||||
traceData->setAddr(addr);
|
|
||||||
traceData->setData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
storeData = data;
|
storeData = data;
|
||||||
|
|
||||||
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
|
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
|
||||||
threadNumber, seqNum, storeData);
|
threadNumber, seqNum, storeData);
|
||||||
return cpu->write(this, data, addr, flags, res);
|
if (traceData) {
|
||||||
|
traceData->setAddr(addr);
|
||||||
|
traceData->setData(data);
|
||||||
|
}
|
||||||
|
storeData = TheISA::htog(data);
|
||||||
|
return writeBytes((uint8_t*)&data, sizeof(T), addr, flags, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
|
@ -334,7 +334,7 @@ class InOrderDynInst : public FastAlloc, public RefCounted
|
||||||
|
|
||||||
PacketDataPtr splitMemData;
|
PacketDataPtr splitMemData;
|
||||||
RequestPtr splitMemReq;
|
RequestPtr splitMemReq;
|
||||||
int splitTotalSize;
|
int totalSize;
|
||||||
int split2ndSize;
|
int split2ndSize;
|
||||||
Addr split2ndAddr;
|
Addr split2ndAddr;
|
||||||
bool split2ndAccess;
|
bool split2ndAccess;
|
||||||
|
@ -637,6 +637,8 @@ class InOrderDynInst : public FastAlloc, public RefCounted
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault read(Addr addr, T &data, unsigned flags);
|
Fault read(Addr addr, T &data, unsigned flags);
|
||||||
|
|
||||||
|
Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does a write to a given address.
|
* Does a write to a given address.
|
||||||
* @param data The data to be written.
|
* @param data The data to be written.
|
||||||
|
@ -649,6 +651,9 @@ class InOrderDynInst : public FastAlloc, public RefCounted
|
||||||
Fault write(T data, Addr addr, unsigned flags,
|
Fault write(T data, Addr addr, unsigned flags,
|
||||||
uint64_t *res);
|
uint64_t *res);
|
||||||
|
|
||||||
|
Fault writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
/** Initiates a memory access - Calculate Eff. Addr & Initiate Memory
|
/** Initiates a memory access - Calculate Eff. Addr & Initiate Memory
|
||||||
* Access Only valid for memory operations.
|
* Access Only valid for memory operations.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -443,9 +443,9 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
||||||
return cache_req->fault;
|
return cache_req->fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
CacheUnit::read(DynInstPtr inst, Addr addr,
|
||||||
|
uint8_t *data, unsigned size, unsigned flags)
|
||||||
{
|
{
|
||||||
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
||||||
assert(cache_req && "Can't Find Instruction for Read!");
|
assert(cache_req && "Can't Find Instruction for Read!");
|
||||||
|
@ -454,14 +454,15 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
unsigned blockSize = this->cachePort->peerBlockSize();
|
unsigned blockSize = this->cachePort->peerBlockSize();
|
||||||
|
|
||||||
//The size of the data we're trying to read.
|
//The size of the data we're trying to read.
|
||||||
int dataSize = sizeof(T);
|
int fullSize = size;
|
||||||
|
inst->totalSize = size;
|
||||||
|
|
||||||
if (inst->traceData) {
|
if (inst->traceData) {
|
||||||
inst->traceData->setAddr(addr);
|
inst->traceData->setAddr(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->split2ndAccess) {
|
if (inst->split2ndAccess) {
|
||||||
dataSize = inst->split2ndSize;
|
size = inst->split2ndSize;
|
||||||
cache_req->splitAccess = true;
|
cache_req->splitAccess = true;
|
||||||
cache_req->split2ndAccess = true;
|
cache_req->split2ndAccess = true;
|
||||||
|
|
||||||
|
@ -473,7 +474,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
//The address of the second part of this access if it needs to be split
|
//The address of the second part of this access if it needs to be split
|
||||||
//across a cache line boundary.
|
//across a cache line boundary.
|
||||||
Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
|
Addr secondAddr = roundDown(addr + size - 1, blockSize);
|
||||||
|
|
||||||
|
|
||||||
if (secondAddr > addr && !inst->split2ndAccess) {
|
if (secondAddr > addr && !inst->split2ndAccess) {
|
||||||
|
@ -483,8 +484,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
// Save All "Total" Split Information
|
// Save All "Total" Split Information
|
||||||
// ==============================
|
// ==============================
|
||||||
inst->splitInst = true;
|
inst->splitInst = true;
|
||||||
inst->splitMemData = new uint8_t[dataSize];
|
inst->splitMemData = new uint8_t[size];
|
||||||
inst->splitTotalSize = dataSize;
|
|
||||||
|
|
||||||
if (!inst->splitInstSked) {
|
if (!inst->splitInstSked) {
|
||||||
// Schedule Split Read/Complete for Instruction
|
// Schedule Split Read/Complete for Instruction
|
||||||
|
@ -517,22 +517,22 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
// Split Information for First Access
|
// Split Information for First Access
|
||||||
// ==============================
|
// ==============================
|
||||||
dataSize = secondAddr - addr;
|
size = secondAddr - addr;
|
||||||
cache_req->splitAccess = true;
|
cache_req->splitAccess = true;
|
||||||
|
|
||||||
// Split Information for Second Access
|
// Split Information for Second Access
|
||||||
// ==============================
|
// ==============================
|
||||||
inst->split2ndSize = addr + sizeof(T) - secondAddr;
|
inst->split2ndSize = addr + fullSize - secondAddr;
|
||||||
inst->split2ndAddr = secondAddr;
|
inst->split2ndAddr = secondAddr;
|
||||||
inst->split2ndDataPtr = inst->splitMemData + dataSize;
|
inst->split2ndDataPtr = inst->splitMemData + size;
|
||||||
inst->split2ndFlags = flags;
|
inst->split2ndFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Read);
|
doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Read);
|
||||||
|
|
||||||
if (cache_req->fault == NoFault) {
|
if (cache_req->fault == NoFault) {
|
||||||
if (!cache_req->splitAccess) {
|
if (!cache_req->splitAccess) {
|
||||||
cache_req->reqData = new uint8_t[dataSize];
|
cache_req->reqData = new uint8_t[size];
|
||||||
doCacheAccess(inst, NULL);
|
doCacheAccess(inst, NULL);
|
||||||
} else {
|
} else {
|
||||||
if (!inst->split2ndAccess) {
|
if (!inst->split2ndAccess) {
|
||||||
|
@ -548,10 +548,9 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
return cache_req->fault;
|
return cache_req->fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
|
||||||
uint64_t *write_res)
|
Addr addr, unsigned flags, uint64_t *write_res)
|
||||||
{
|
{
|
||||||
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
||||||
assert(cache_req && "Can't Find Instruction for Write!");
|
assert(cache_req && "Can't Find Instruction for Write!");
|
||||||
|
@ -559,16 +558,16 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
||||||
// The block size of our peer
|
// The block size of our peer
|
||||||
unsigned blockSize = this->cachePort->peerBlockSize();
|
unsigned blockSize = this->cachePort->peerBlockSize();
|
||||||
|
|
||||||
//The size of the data we're trying to read.
|
//The size of the data we're trying to write.
|
||||||
int dataSize = sizeof(T);
|
int fullSize = size;
|
||||||
|
inst->totalSize = size;
|
||||||
|
|
||||||
if (inst->traceData) {
|
if (inst->traceData) {
|
||||||
inst->traceData->setAddr(addr);
|
inst->traceData->setAddr(addr);
|
||||||
inst->traceData->setData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->split2ndAccess) {
|
if (inst->split2ndAccess) {
|
||||||
dataSize = inst->split2ndSize;
|
size = inst->split2ndSize;
|
||||||
cache_req->splitAccess = true;
|
cache_req->splitAccess = true;
|
||||||
cache_req->split2ndAccess = true;
|
cache_req->split2ndAccess = true;
|
||||||
|
|
||||||
|
@ -579,7 +578,7 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
||||||
|
|
||||||
//The address of the second part of this access if it needs to be split
|
//The address of the second part of this access if it needs to be split
|
||||||
//across a cache line boundary.
|
//across a cache line boundary.
|
||||||
Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
|
Addr secondAddr = roundDown(addr + size - 1, blockSize);
|
||||||
|
|
||||||
if (secondAddr > addr && !inst->split2ndAccess) {
|
if (secondAddr > addr && !inst->split2ndAccess) {
|
||||||
|
|
||||||
|
@ -589,7 +588,6 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
||||||
// Save All "Total" Split Information
|
// Save All "Total" Split Information
|
||||||
// ==============================
|
// ==============================
|
||||||
inst->splitInst = true;
|
inst->splitInst = true;
|
||||||
inst->splitTotalSize = dataSize;
|
|
||||||
|
|
||||||
if (!inst->splitInstSked) {
|
if (!inst->splitInstSked) {
|
||||||
// Schedule Split Read/Complete for Instruction
|
// Schedule Split Read/Complete for Instruction
|
||||||
|
@ -624,25 +622,25 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
||||||
|
|
||||||
// Split Information for First Access
|
// Split Information for First Access
|
||||||
// ==============================
|
// ==============================
|
||||||
dataSize = secondAddr - addr;
|
size = secondAddr - addr;
|
||||||
cache_req->splitAccess = true;
|
cache_req->splitAccess = true;
|
||||||
|
|
||||||
// Split Information for Second Access
|
// Split Information for Second Access
|
||||||
// ==============================
|
// ==============================
|
||||||
inst->split2ndSize = addr + sizeof(T) - secondAddr;
|
inst->split2ndSize = addr + fullSize - secondAddr;
|
||||||
inst->split2ndAddr = secondAddr;
|
inst->split2ndAddr = secondAddr;
|
||||||
inst->split2ndStoreDataPtr = &cache_req->inst->storeData;
|
inst->split2ndStoreDataPtr = &cache_req->inst->storeData;
|
||||||
inst->split2ndStoreDataPtr += dataSize;
|
inst->split2ndStoreDataPtr += size;
|
||||||
inst->split2ndFlags = flags;
|
inst->split2ndFlags = flags;
|
||||||
inst->splitInstSked = true;
|
inst->splitInstSked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Write);
|
doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Write);
|
||||||
|
|
||||||
if (cache_req->fault == NoFault) {
|
if (cache_req->fault == NoFault) {
|
||||||
if (!cache_req->splitAccess) {
|
if (!cache_req->splitAccess) {
|
||||||
// Remove this line since storeData is saved in INST?
|
// Remove this line since storeData is saved in INST?
|
||||||
cache_req->reqData = new uint8_t[dataSize];
|
cache_req->reqData = new uint8_t[size];
|
||||||
doCacheAccess(inst, write_res);
|
doCacheAccess(inst, write_res);
|
||||||
} else {
|
} else {
|
||||||
doCacheAccess(inst, write_res, cache_req);
|
doCacheAccess(inst, write_res, cache_req);
|
||||||
|
@ -729,8 +727,8 @@ CacheUnit::execute(int slot_num)
|
||||||
cache_req->inst->split2ndAddr);
|
cache_req->inst->split2ndAddr);
|
||||||
inst->split2ndAccess = true;
|
inst->split2ndAccess = true;
|
||||||
assert(inst->split2ndAddr != 0);
|
assert(inst->split2ndAddr != 0);
|
||||||
read(inst, inst->split2ndAddr, inst->split2ndData,
|
read(inst, inst->split2ndAddr, &inst->split2ndData,
|
||||||
inst->split2ndFlags);
|
inst->totalSize, inst->split2ndFlags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InitSecondSplitWrite:
|
case InitSecondSplitWrite:
|
||||||
|
@ -741,8 +739,8 @@ CacheUnit::execute(int slot_num)
|
||||||
|
|
||||||
inst->split2ndAccess = true;
|
inst->split2ndAccess = true;
|
||||||
assert(inst->split2ndAddr != 0);
|
assert(inst->split2ndAddr != 0);
|
||||||
write(inst, inst->split2ndAddr, inst->split2ndData,
|
write(inst, &inst->split2ndData, inst->totalSize,
|
||||||
inst->split2ndFlags, NULL);
|
inst->split2ndAddr, inst->split2ndFlags, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1075,7 +1073,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
|
||||||
if (inst->splitFinishCnt == 2) {
|
if (inst->splitFinishCnt == 2) {
|
||||||
cache_req->memReq->setVirt(0/*inst->tid*/,
|
cache_req->memReq->setVirt(0/*inst->tid*/,
|
||||||
inst->getMemAddr(),
|
inst->getMemAddr(),
|
||||||
inst->splitTotalSize,
|
inst->totalSize,
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
@ -1301,113 +1299,3 @@ CacheUnit::squash(DynInstPtr inst, int stage_num,
|
||||||
freeSlot(slot_remove_list[i]);
|
freeSlot(slot_remove_list[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extra Template Definitions
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, Twin64_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, uint64_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, uint32_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, uint16_t &data, unsigned flags);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, uint8_t &data, unsigned flags);
|
|
||||||
|
|
||||||
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, double &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(inst, addr, *(uint64_t*)&data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, float &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(inst, addr, *(uint32_t*)&data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, int32_t &data, unsigned flags)
|
|
||||||
{
|
|
||||||
return read(inst, addr, (uint32_t&)data, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, Twin32_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, Twin64_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, uint64_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, uint32_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, uint16_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
template
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, uint8_t data, Addr addr,
|
|
||||||
unsigned flags, uint64_t *res);
|
|
||||||
|
|
||||||
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, double data, Addr addr, unsigned flags,
|
|
||||||
uint64_t *res)
|
|
||||||
{
|
|
||||||
return write(inst, *(uint64_t*)&data, addr, flags, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, float data, Addr addr, unsigned flags,
|
|
||||||
uint64_t *res)
|
|
||||||
{
|
|
||||||
return write(inst, *(uint32_t*)&data, addr, flags, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
Fault
|
|
||||||
CacheUnit::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags,
|
|
||||||
uint64_t *res)
|
|
||||||
{
|
|
||||||
return write(inst, (uint32_t)data, addr, flags, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -161,12 +161,11 @@ class CacheUnit : public Resource
|
||||||
/** Returns a specific port. */
|
/** Returns a specific port. */
|
||||||
Port *getPort(const std::string &if_name, int idx);
|
Port *getPort(const std::string &if_name, int idx);
|
||||||
|
|
||||||
template <class T>
|
Fault read(DynInstPtr inst, Addr addr,
|
||||||
Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
|
uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
template <class T>
|
Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
|
||||||
Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
Addr addr, unsigned flags, uint64_t *res);
|
||||||
uint64_t *res);
|
|
||||||
|
|
||||||
Fault doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
Fault doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
||||||
int flags, TheISA::TLB::Mode tlb_mode);
|
int flags, TheISA::TLB::Mode tlb_mode);
|
||||||
|
|
|
@ -702,18 +702,16 @@ class FullO3CPU : public BaseO3CPU
|
||||||
std::vector<ThreadID> tids;
|
std::vector<ThreadID> tids;
|
||||||
|
|
||||||
/** CPU read function, forwards read to LSQ. */
|
/** CPU read function, forwards read to LSQ. */
|
||||||
template <class T>
|
|
||||||
Fault read(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
|
Fault read(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
|
||||||
T &data, int load_idx)
|
uint8_t *data, int load_idx)
|
||||||
{
|
{
|
||||||
return this->iew.ldstQueue.read(req, sreqLow, sreqHigh,
|
return this->iew.ldstQueue.read(req, sreqLow, sreqHigh,
|
||||||
data, load_idx);
|
data, load_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** CPU write function, forwards write to LSQ. */
|
/** CPU write function, forwards write to LSQ. */
|
||||||
template <class T>
|
|
||||||
Fault write(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
|
Fault write(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
|
||||||
T &data, int store_idx)
|
uint8_t *data, int store_idx)
|
||||||
{
|
{
|
||||||
return this->iew.ldstQueue.write(req, sreqLow, sreqHigh,
|
return this->iew.ldstQueue.write(req, sreqLow, sreqHigh,
|
||||||
data, store_idx);
|
data, store_idx);
|
||||||
|
|
|
@ -273,16 +273,14 @@ class LSQ {
|
||||||
/** Executes a read operation, using the load specified at the load
|
/** Executes a read operation, using the load specified at the load
|
||||||
* index.
|
* index.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
|
||||||
Fault read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
Fault read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
||||||
T &data, int load_idx);
|
uint8_t *data, int load_idx);
|
||||||
|
|
||||||
/** Executes a store operation, using the store specified at the store
|
/** Executes a store operation, using the store specified at the store
|
||||||
* index.
|
* index.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
|
||||||
Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
||||||
T &data, int store_idx);
|
uint8_t *data, int store_idx);
|
||||||
|
|
||||||
/** The CPU pointer. */
|
/** The CPU pointer. */
|
||||||
O3CPU *cpu;
|
O3CPU *cpu;
|
||||||
|
@ -371,10 +369,9 @@ class LSQ {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
||||||
T &data, int load_idx)
|
uint8_t *data, int load_idx)
|
||||||
{
|
{
|
||||||
ThreadID tid = req->threadId();
|
ThreadID tid = req->threadId();
|
||||||
|
|
||||||
|
@ -382,10 +379,9 @@ LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
LSQ<Impl>::write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
LSQ<Impl>::write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
|
||||||
T &data, int store_idx)
|
uint8_t *data, int store_idx)
|
||||||
{
|
{
|
||||||
ThreadID tid = req->threadId();
|
ThreadID tid = req->threadId();
|
||||||
|
|
||||||
|
|
|
@ -474,14 +474,12 @@ class LSQUnit {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Executes the load at the given index. */
|
/** Executes the load at the given index. */
|
||||||
template <class T>
|
Fault read(Request *req, Request *sreqLow, Request *sreqHigh,
|
||||||
Fault read(Request *req, Request *sreqLow, Request *sreqHigh, T &data,
|
uint8_t *data, int load_idx);
|
||||||
int load_idx);
|
|
||||||
|
|
||||||
/** Executes the store at the given index. */
|
/** Executes the store at the given index. */
|
||||||
template <class T>
|
Fault write(Request *req, Request *sreqLow, Request *sreqHigh,
|
||||||
Fault write(Request *req, Request *sreqLow, Request *sreqHigh, T &data,
|
uint8_t *data, int store_idx);
|
||||||
int store_idx);
|
|
||||||
|
|
||||||
/** Returns the index of the head load instruction. */
|
/** Returns the index of the head load instruction. */
|
||||||
int getLoadHead() { return loadHead; }
|
int getLoadHead() { return loadHead; }
|
||||||
|
@ -514,10 +512,9 @@ class LSQUnit {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
|
LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
|
||||||
T &data, int load_idx)
|
uint8_t *data, int load_idx)
|
||||||
{
|
{
|
||||||
DynInstPtr load_inst = loadQueue[load_idx];
|
DynInstPtr load_inst = loadQueue[load_idx];
|
||||||
|
|
||||||
|
@ -605,7 +602,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
|
||||||
// Get shift amount for offset into the store's data.
|
// Get shift amount for offset into the store's data.
|
||||||
int shift_amt = req->getVaddr() & (store_size - 1);
|
int shift_amt = req->getVaddr() & (store_size - 1);
|
||||||
|
|
||||||
memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T));
|
memcpy(data, storeQueue[store_idx].data + shift_amt,
|
||||||
|
req->getSize());
|
||||||
|
|
||||||
assert(!load_inst->memData);
|
assert(!load_inst->memData);
|
||||||
load_inst->memData = new uint8_t[64];
|
load_inst->memData = new uint8_t[64];
|
||||||
|
@ -809,10 +807,9 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
LSQUnit<Impl>::write(Request *req, Request *sreqLow, Request *sreqHigh,
|
LSQUnit<Impl>::write(Request *req, Request *sreqLow, Request *sreqHigh,
|
||||||
T &data, int store_idx)
|
uint8_t *data, int store_idx)
|
||||||
{
|
{
|
||||||
assert(storeQueue[store_idx].inst);
|
assert(storeQueue[store_idx].inst);
|
||||||
|
|
||||||
|
@ -824,17 +821,17 @@ LSQUnit<Impl>::write(Request *req, Request *sreqLow, Request *sreqHigh,
|
||||||
storeQueue[store_idx].req = req;
|
storeQueue[store_idx].req = req;
|
||||||
storeQueue[store_idx].sreqLow = sreqLow;
|
storeQueue[store_idx].sreqLow = sreqLow;
|
||||||
storeQueue[store_idx].sreqHigh = sreqHigh;
|
storeQueue[store_idx].sreqHigh = sreqHigh;
|
||||||
storeQueue[store_idx].size = sizeof(T);
|
unsigned size = req->getSize();
|
||||||
|
storeQueue[store_idx].size = size;
|
||||||
|
assert(size <= sizeof(storeQueue[store_idx].data));
|
||||||
|
|
||||||
// Split stores can only occur in ISAs with unaligned memory accesses. If
|
// Split stores can only occur in ISAs with unaligned memory accesses. If
|
||||||
// a store request has been split, sreqLow and sreqHigh will be non-null.
|
// a store request has been split, sreqLow and sreqHigh will be non-null.
|
||||||
if (TheISA::HasUnalignedMemAcc && sreqLow) {
|
if (TheISA::HasUnalignedMemAcc && sreqLow) {
|
||||||
storeQueue[store_idx].isSplit = true;
|
storeQueue[store_idx].isSplit = true;
|
||||||
}
|
}
|
||||||
assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
|
|
||||||
|
|
||||||
T gData = htog(data);
|
memcpy(storeQueue[store_idx].data, data, size);
|
||||||
memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
|
|
||||||
|
|
||||||
// This function only writes the data to the store queue, so no fault
|
// This function only writes the data to the store queue, so no fault
|
||||||
// can happen here.
|
// can happen here.
|
||||||
|
|
|
@ -294,9 +294,9 @@ AtomicSimpleCPU::suspendContext(int thread_num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
AtomicSimpleCPU::readBytes(Addr addr, uint8_t * data,
|
||||||
|
unsigned size, unsigned flags)
|
||||||
{
|
{
|
||||||
// use the CPU's statically allocated read request and packet objects
|
// use the CPU's statically allocated read request and packet objects
|
||||||
Request *req = &data_read_req;
|
Request *req = &data_read_req;
|
||||||
|
@ -308,21 +308,19 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
//The block size of our peer.
|
//The block size of our peer.
|
||||||
unsigned blockSize = dcachePort.peerBlockSize();
|
unsigned blockSize = dcachePort.peerBlockSize();
|
||||||
//The size of the data we're trying to read.
|
//The size of the data we're trying to read.
|
||||||
int dataSize = sizeof(T);
|
int fullSize = size;
|
||||||
|
|
||||||
uint8_t * dataPtr = (uint8_t *)&data;
|
|
||||||
|
|
||||||
//The address of the second part of this access if it needs to be split
|
//The address of the second part of this access if it needs to be split
|
||||||
//across a cache line boundary.
|
//across a cache line boundary.
|
||||||
Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
|
Addr secondAddr = roundDown(addr + size - 1, blockSize);
|
||||||
|
|
||||||
if (secondAddr > addr)
|
if (secondAddr > addr)
|
||||||
dataSize = secondAddr - addr;
|
size = secondAddr - addr;
|
||||||
|
|
||||||
dcache_latency = 0;
|
dcache_latency = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
req->setVirt(0, addr, dataSize, flags, thread->readPC());
|
req->setVirt(0, addr, size, flags, thread->readPC());
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
|
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
|
||||||
|
@ -332,7 +330,7 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
Packet pkt = Packet(req,
|
Packet pkt = Packet(req,
|
||||||
req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
|
req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
|
||||||
Packet::Broadcast);
|
Packet::Broadcast);
|
||||||
pkt.dataStatic(dataPtr);
|
pkt.dataStatic(data);
|
||||||
|
|
||||||
if (req->isMmapedIpr())
|
if (req->isMmapedIpr())
|
||||||
dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
|
dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
|
||||||
|
@ -363,10 +361,6 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
//If we don't need to access a second cache line, stop now.
|
//If we don't need to access a second cache line, stop now.
|
||||||
if (secondAddr <= addr)
|
if (secondAddr <= addr)
|
||||||
{
|
{
|
||||||
data = gtoh(data);
|
|
||||||
if (traceData) {
|
|
||||||
traceData->setData(data);
|
|
||||||
}
|
|
||||||
if (req->isLocked() && fault == NoFault) {
|
if (req->isLocked() && fault == NoFault) {
|
||||||
assert(!locked);
|
assert(!locked);
|
||||||
locked = true;
|
locked = true;
|
||||||
|
@ -379,14 +373,30 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Move the pointer we're reading into to the correct location.
|
//Move the pointer we're reading into to the correct location.
|
||||||
dataPtr += dataSize;
|
data += size;
|
||||||
//Adjust the size to get the remaining bytes.
|
//Adjust the size to get the remaining bytes.
|
||||||
dataSize = addr + sizeof(T) - secondAddr;
|
size = addr + fullSize - secondAddr;
|
||||||
//And access the right address.
|
//And access the right address.
|
||||||
addr = secondAddr;
|
addr = secondAddr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Fault
|
||||||
|
AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
|
{
|
||||||
|
uint8_t *dataPtr = (uint8_t *)&data;
|
||||||
|
memset(dataPtr, 0, sizeof(data));
|
||||||
|
Fault fault = readBytes(addr, dataPtr, sizeof(data), flags);
|
||||||
|
if (fault == NoFault) {
|
||||||
|
data = gtoh(data);
|
||||||
|
if (traceData)
|
||||||
|
traceData->setData(data);
|
||||||
|
}
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
template
|
template
|
||||||
|
@ -438,38 +448,33 @@ AtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
AtomicSimpleCPU::writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res)
|
||||||
{
|
{
|
||||||
// use the CPU's statically allocated write request and packet objects
|
// use the CPU's statically allocated write request and packet objects
|
||||||
Request *req = &data_write_req;
|
Request *req = &data_write_req;
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
traceData->setAddr(addr);
|
traceData->setAddr(addr);
|
||||||
traceData->setData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data = htog(data);
|
|
||||||
|
|
||||||
//The block size of our peer.
|
//The block size of our peer.
|
||||||
unsigned blockSize = dcachePort.peerBlockSize();
|
unsigned blockSize = dcachePort.peerBlockSize();
|
||||||
//The size of the data we're trying to read.
|
//The size of the data we're trying to read.
|
||||||
int dataSize = sizeof(T);
|
int fullSize = size;
|
||||||
|
|
||||||
uint8_t * dataPtr = (uint8_t *)&data;
|
|
||||||
|
|
||||||
//The address of the second part of this access if it needs to be split
|
//The address of the second part of this access if it needs to be split
|
||||||
//across a cache line boundary.
|
//across a cache line boundary.
|
||||||
Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
|
Addr secondAddr = roundDown(addr + size - 1, blockSize);
|
||||||
|
|
||||||
if(secondAddr > addr)
|
if(secondAddr > addr)
|
||||||
dataSize = secondAddr - addr;
|
size = secondAddr - addr;
|
||||||
|
|
||||||
dcache_latency = 0;
|
dcache_latency = 0;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
req->setVirt(0, addr, dataSize, flags, thread->readPC());
|
req->setVirt(0, addr, size, flags, thread->readPC());
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
|
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
|
||||||
|
@ -492,7 +497,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
|
||||||
if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) {
|
if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) {
|
||||||
Packet pkt = Packet(req, cmd, Packet::Broadcast);
|
Packet pkt = Packet(req, cmd, Packet::Broadcast);
|
||||||
pkt.dataStatic(dataPtr);
|
pkt.dataStatic(data);
|
||||||
|
|
||||||
if (req->isMmapedIpr()) {
|
if (req->isMmapedIpr()) {
|
||||||
dcache_latency +=
|
dcache_latency +=
|
||||||
|
@ -508,7 +513,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
|
||||||
if (req->isSwap()) {
|
if (req->isSwap()) {
|
||||||
assert(res);
|
assert(res);
|
||||||
*res = pkt.get<T>();
|
memcpy(res, pkt.getPtr<uint8_t>(), fullSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,15 +542,32 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Move the pointer we're reading into to the correct location.
|
//Move the pointer we're reading into to the correct location.
|
||||||
dataPtr += dataSize;
|
data += size;
|
||||||
//Adjust the size to get the remaining bytes.
|
//Adjust the size to get the remaining bytes.
|
||||||
dataSize = addr + sizeof(T) - secondAddr;
|
size = addr + fullSize - secondAddr;
|
||||||
//And access the right address.
|
//And access the right address.
|
||||||
addr = secondAddr;
|
addr = secondAddr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Fault
|
||||||
|
AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
{
|
||||||
|
uint8_t *dataPtr = (uint8_t *)&data;
|
||||||
|
if (traceData)
|
||||||
|
traceData->setData(data);
|
||||||
|
data = htog(data);
|
||||||
|
|
||||||
|
Fault fault = writeBytes(dataPtr, sizeof(data), addr, flags, res);
|
||||||
|
if (fault == NoFault && data_write_req.isSwap()) {
|
||||||
|
*res = gtoh((T)*res);
|
||||||
|
}
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
template
|
template
|
||||||
|
|
|
@ -134,9 +134,14 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault read(Addr addr, T &data, unsigned flags);
|
Fault read(Addr addr, T &data, unsigned flags);
|
||||||
|
|
||||||
|
Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
|
Fault writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print state of address in memory system via PrintReq (for
|
* Print state of address in memory system via PrintReq (for
|
||||||
* debugging).
|
* debugging).
|
||||||
|
|
|
@ -414,26 +414,25 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
|
||||||
pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
|
pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
TimingSimpleCPU::readBytes(Addr addr, uint8_t *data,
|
||||||
|
unsigned size, unsigned flags)
|
||||||
{
|
{
|
||||||
Fault fault;
|
Fault fault;
|
||||||
const int asid = 0;
|
const int asid = 0;
|
||||||
const ThreadID tid = 0;
|
const ThreadID tid = 0;
|
||||||
const Addr pc = thread->readPC();
|
const Addr pc = thread->readPC();
|
||||||
unsigned block_size = dcachePort.peerBlockSize();
|
unsigned block_size = dcachePort.peerBlockSize();
|
||||||
int data_size = sizeof(T);
|
|
||||||
BaseTLB::Mode mode = BaseTLB::Read;
|
BaseTLB::Mode mode = BaseTLB::Read;
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
traceData->setAddr(addr);
|
traceData->setAddr(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestPtr req = new Request(asid, addr, data_size,
|
RequestPtr req = new Request(asid, addr, size,
|
||||||
flags, pc, _cpuId, tid);
|
flags, pc, _cpuId, tid);
|
||||||
|
|
||||||
Addr split_addr = roundDown(addr + data_size - 1, block_size);
|
Addr split_addr = roundDown(addr + size - 1, block_size);
|
||||||
assert(split_addr <= addr || split_addr - addr < block_size);
|
assert(split_addr <= addr || split_addr - addr < block_size);
|
||||||
|
|
||||||
_status = DTBWaitResponse;
|
_status = DTBWaitResponse;
|
||||||
|
@ -443,7 +442,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
req->splitOnVaddr(split_addr, req1, req2);
|
req->splitOnVaddr(split_addr, req1, req2);
|
||||||
|
|
||||||
WholeTranslationState *state =
|
WholeTranslationState *state =
|
||||||
new WholeTranslationState(req, req1, req2, (uint8_t *)(new T),
|
new WholeTranslationState(req, req1, req2, new uint8_t[size],
|
||||||
NULL, mode);
|
NULL, mode);
|
||||||
DataTranslation<TimingSimpleCPU> *trans1 =
|
DataTranslation<TimingSimpleCPU> *trans1 =
|
||||||
new DataTranslation<TimingSimpleCPU>(this, state, 0);
|
new DataTranslation<TimingSimpleCPU>(this, state, 0);
|
||||||
|
@ -454,7 +453,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
thread->dtb->translateTiming(req2, tc, trans2, mode);
|
thread->dtb->translateTiming(req2, tc, trans2, mode);
|
||||||
} else {
|
} else {
|
||||||
WholeTranslationState *state =
|
WholeTranslationState *state =
|
||||||
new WholeTranslationState(req, (uint8_t *)(new T), NULL, mode);
|
new WholeTranslationState(req, new uint8_t[size], NULL, mode);
|
||||||
DataTranslation<TimingSimpleCPU> *translation
|
DataTranslation<TimingSimpleCPU> *translation
|
||||||
= new DataTranslation<TimingSimpleCPU>(this, state);
|
= new DataTranslation<TimingSimpleCPU>(this, state);
|
||||||
thread->dtb->translateTiming(req, tc, translation, mode);
|
thread->dtb->translateTiming(req, tc, translation, mode);
|
||||||
|
@ -463,6 +462,13 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Fault
|
||||||
|
TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
|
{
|
||||||
|
return readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
template
|
template
|
||||||
|
@ -532,30 +538,26 @@ TimingSimpleCPU::handleWritePacket()
|
||||||
return dcache_pkt == NULL;
|
return dcache_pkt == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
Fault
|
Fault
|
||||||
TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
TimingSimpleCPU::writeTheseBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res)
|
||||||
{
|
{
|
||||||
const int asid = 0;
|
const int asid = 0;
|
||||||
const ThreadID tid = 0;
|
const ThreadID tid = 0;
|
||||||
const Addr pc = thread->readPC();
|
const Addr pc = thread->readPC();
|
||||||
unsigned block_size = dcachePort.peerBlockSize();
|
unsigned block_size = dcachePort.peerBlockSize();
|
||||||
int data_size = sizeof(T);
|
|
||||||
BaseTLB::Mode mode = BaseTLB::Write;
|
BaseTLB::Mode mode = BaseTLB::Write;
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
traceData->setAddr(addr);
|
traceData->setAddr(addr);
|
||||||
traceData->setData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestPtr req = new Request(asid, addr, data_size,
|
RequestPtr req = new Request(asid, addr, size,
|
||||||
flags, pc, _cpuId, tid);
|
flags, pc, _cpuId, tid);
|
||||||
|
|
||||||
Addr split_addr = roundDown(addr + data_size - 1, block_size);
|
Addr split_addr = roundDown(addr + size - 1, block_size);
|
||||||
assert(split_addr <= addr || split_addr - addr < block_size);
|
assert(split_addr <= addr || split_addr - addr < block_size);
|
||||||
|
|
||||||
T *dataP = new T;
|
|
||||||
*dataP = TheISA::htog(data);
|
|
||||||
_status = DTBWaitResponse;
|
_status = DTBWaitResponse;
|
||||||
if (split_addr > addr) {
|
if (split_addr > addr) {
|
||||||
RequestPtr req1, req2;
|
RequestPtr req1, req2;
|
||||||
|
@ -563,8 +565,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
req->splitOnVaddr(split_addr, req1, req2);
|
req->splitOnVaddr(split_addr, req1, req2);
|
||||||
|
|
||||||
WholeTranslationState *state =
|
WholeTranslationState *state =
|
||||||
new WholeTranslationState(req, req1, req2, (uint8_t *)dataP,
|
new WholeTranslationState(req, req1, req2, data, res, mode);
|
||||||
res, mode);
|
|
||||||
DataTranslation<TimingSimpleCPU> *trans1 =
|
DataTranslation<TimingSimpleCPU> *trans1 =
|
||||||
new DataTranslation<TimingSimpleCPU>(this, state, 0);
|
new DataTranslation<TimingSimpleCPU>(this, state, 0);
|
||||||
DataTranslation<TimingSimpleCPU> *trans2 =
|
DataTranslation<TimingSimpleCPU> *trans2 =
|
||||||
|
@ -574,7 +575,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
thread->dtb->translateTiming(req2, tc, trans2, mode);
|
thread->dtb->translateTiming(req2, tc, trans2, mode);
|
||||||
} else {
|
} else {
|
||||||
WholeTranslationState *state =
|
WholeTranslationState *state =
|
||||||
new WholeTranslationState(req, (uint8_t *)dataP, res, mode);
|
new WholeTranslationState(req, data, res, mode);
|
||||||
DataTranslation<TimingSimpleCPU> *translation =
|
DataTranslation<TimingSimpleCPU> *translation =
|
||||||
new DataTranslation<TimingSimpleCPU>(this, state);
|
new DataTranslation<TimingSimpleCPU>(this, state);
|
||||||
thread->dtb->translateTiming(req, tc, translation, mode);
|
thread->dtb->translateTiming(req, tc, translation, mode);
|
||||||
|
@ -584,6 +585,28 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fault
|
||||||
|
TimingSimpleCPU::writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
{
|
||||||
|
uint8_t *newData = new uint8_t[size];
|
||||||
|
memcpy(newData, data, size);
|
||||||
|
return writeTheseBytes(newData, size, addr, flags, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Fault
|
||||||
|
TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
{
|
||||||
|
if (traceData) {
|
||||||
|
traceData->setData(data);
|
||||||
|
}
|
||||||
|
T *dataP = new T;
|
||||||
|
*dataP = TheISA::htog(data);
|
||||||
|
|
||||||
|
return writeTheseBytes((uint8_t *)dataP, sizeof(T), addr, flags, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
template
|
template
|
||||||
|
|
|
@ -251,9 +251,14 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault read(Addr addr, T &data, unsigned flags);
|
Fault read(Addr addr, T &data, unsigned flags);
|
||||||
|
|
||||||
|
Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
|
Fault writeBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
void fetch();
|
void fetch();
|
||||||
void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
|
void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
|
||||||
void completeIfetch(PacketPtr );
|
void completeIfetch(PacketPtr );
|
||||||
|
@ -274,6 +279,11 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// The backend for writeBytes and write. It's the same as writeBytes, but
|
||||||
|
// doesn't make a copy of data.
|
||||||
|
Fault writeTheseBytes(uint8_t *data, unsigned size,
|
||||||
|
Addr addr, unsigned flags, uint64_t *res);
|
||||||
|
|
||||||
typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
|
typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
|
||||||
FetchEvent fetchEvent;
|
FetchEvent fetchEvent;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue