CPU: Add readBytes and writeBytes functions to the exec contexts.

This commit is contained in:
Gabe Black 2010-08-13 06:16:02 -07:00
parent 65dbcc6ea1
commit aa8c6e9c95
15 changed files with 253 additions and 366 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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.
*/ */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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