template <class T>
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.
* @param data The data to be written.
template <class T>
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. */
void splitRequest(RequestPtr req, RequestPtr &sreqLow,
RequestPtr &sreqHigh);
};
template<class Impl>
-template<class T>
-inline Fault
-BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
+Fault
+BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data,
+ unsigned size, unsigned flags)
{
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);
Request *sreqLow = NULL;
effAddrValid = true;
fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
} 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
// instruction as executed.
this->setExecuted();
if (traceData) {
traceData->setAddr(addr);
- traceData->setData(data);
}
return fault;
template<class Impl>
template<class T>
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) {
- traceData->setAddr(addr);
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;
- Request *req = new Request(asid, addr, sizeof(T), flags, this->PC,
+ Request *req = new Request(asid, addr, size, flags, this->PC,
thread->contextId(), threadNumber);
Request *sreqLow = NULL;
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>
inline void
BaseDynInst<Impl>::splitRequest(RequestPtr req, RequestPtr &sreqLow,
template <class T>
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
* flags. Writes data to memory. For store conditionals, returns
* the result of the store in res. */
template <class T>
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
* given flags. */
void prefetch(Addr addr, unsigned flags);
return dtb_res->tlb();
}
-template <class T>
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
// you want to run w/out caches?
CacheUnit *cache_res =
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
-InOrderCPU::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags);
-
-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)
+InOrderCPU::write(DynInstPtr inst, uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *write_res)
{
//@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
// you want to run w/out caches?
CacheUnit *cache_res =
dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
- return cache_res->write(inst, data, 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);
+ return cache_res->write(inst, data, size, addr, flags, write_res);
}
/** Forwards an instruction read to the appropriate data
* resource (indexes into Resource Pool thru "dataPortIdx")
*/
- template <class T>
- Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
+ Fault read(DynInstPtr inst, Addr addr,
+ uint8_t *data, unsigned size, unsigned flags);
/** Forwards an instruction write. to the appropriate data
* resource (indexes into Resource Pool thru "dataPortIdx")
*/
- template <class T>
- Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags,
- uint64_t *write_res = NULL);
+ Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *write_res = NULL);
/** Forwards an instruction prefetch to the appropriate data
* resource (indexes into Resource Pool thru "dataPortIdx")
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>
inline Fault
InOrderDynInst::read(Addr addr, T &data, unsigned flags)
traceData->setAddr(addr);
traceData->setData(data);
}
-
- return cpu->read(this, addr, data, flags);
+ Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
+ data = TheISA::gtoh(data);
+ if (traceData)
+ traceData->setData(data);
+ return fault;
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
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>
inline Fault
InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
- if (traceData) {
- traceData->setAddr(addr);
- traceData->setData(data);
- }
-
storeData = data;
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
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
PacketDataPtr splitMemData;
RequestPtr splitMemReq;
- int splitTotalSize;
+ int totalSize;
int split2ndSize;
Addr split2ndAddr;
bool split2ndAccess;
template <class T>
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.
* @param data The data to be written.
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);
+
/** Initiates a memory access - Calculate Eff. Addr & Initiate Memory
* Access Only valid for memory operations.
*/
return cache_req->fault;
}
-template <class T>
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));
assert(cache_req && "Can't Find Instruction for Read!");
unsigned blockSize = this->cachePort->peerBlockSize();
//The size of the data we're trying to read.
- int dataSize = sizeof(T);
+ int fullSize = size;
+ inst->totalSize = size;
if (inst->traceData) {
inst->traceData->setAddr(addr);
}
if (inst->split2ndAccess) {
- dataSize = inst->split2ndSize;
+ size = inst->split2ndSize;
cache_req->splitAccess = true;
cache_req->split2ndAccess = true;
//The address of the second part of this access if it needs to be split
//across a cache line boundary.
- Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+ Addr secondAddr = roundDown(addr + size - 1, blockSize);
if (secondAddr > addr && !inst->split2ndAccess) {
// Save All "Total" Split Information
// ==============================
inst->splitInst = true;
- inst->splitMemData = new uint8_t[dataSize];
- inst->splitTotalSize = dataSize;
+ inst->splitMemData = new uint8_t[size];
if (!inst->splitInstSked) {
// Schedule Split Read/Complete for Instruction
// Split Information for First Access
// ==============================
- dataSize = secondAddr - addr;
+ size = secondAddr - addr;
cache_req->splitAccess = true;
// Split Information for Second Access
// ==============================
- inst->split2ndSize = addr + sizeof(T) - secondAddr;
+ inst->split2ndSize = addr + fullSize - secondAddr;
inst->split2ndAddr = secondAddr;
- inst->split2ndDataPtr = inst->splitMemData + dataSize;
+ inst->split2ndDataPtr = inst->splitMemData + size;
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->splitAccess) {
- cache_req->reqData = new uint8_t[dataSize];
+ cache_req->reqData = new uint8_t[size];
doCacheAccess(inst, NULL);
} else {
if (!inst->split2ndAccess) {
return cache_req->fault;
}
-template <class T>
Fault
-CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
- uint64_t *write_res)
+CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *write_res)
{
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
assert(cache_req && "Can't Find Instruction for Write!");
// The block size of our peer
unsigned blockSize = this->cachePort->peerBlockSize();
- //The size of the data we're trying to read.
- int dataSize = sizeof(T);
+ //The size of the data we're trying to write.
+ int fullSize = size;
+ inst->totalSize = size;
if (inst->traceData) {
inst->traceData->setAddr(addr);
- inst->traceData->setData(data);
}
if (inst->split2ndAccess) {
- dataSize = inst->split2ndSize;
+ size = inst->split2ndSize;
cache_req->splitAccess = true;
cache_req->split2ndAccess = true;
//The address of the second part of this access if it needs to be split
//across a cache line boundary.
- Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+ Addr secondAddr = roundDown(addr + size - 1, blockSize);
if (secondAddr > addr && !inst->split2ndAccess) {
// Save All "Total" Split Information
// ==============================
inst->splitInst = true;
- inst->splitTotalSize = dataSize;
if (!inst->splitInstSked) {
// Schedule Split Read/Complete for Instruction
// Split Information for First Access
// ==============================
- dataSize = secondAddr - addr;
+ size = secondAddr - addr;
cache_req->splitAccess = true;
// Split Information for Second Access
// ==============================
- inst->split2ndSize = addr + sizeof(T) - secondAddr;
+ inst->split2ndSize = addr + fullSize - secondAddr;
inst->split2ndAddr = secondAddr;
inst->split2ndStoreDataPtr = &cache_req->inst->storeData;
- inst->split2ndStoreDataPtr += dataSize;
+ inst->split2ndStoreDataPtr += size;
inst->split2ndFlags = flags;
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->splitAccess) {
// 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);
} else {
doCacheAccess(inst, write_res, cache_req);
cache_req->inst->split2ndAddr);
inst->split2ndAccess = true;
assert(inst->split2ndAddr != 0);
- read(inst, inst->split2ndAddr, inst->split2ndData,
- inst->split2ndFlags);
+ read(inst, inst->split2ndAddr, &inst->split2ndData,
+ inst->totalSize, inst->split2ndFlags);
break;
case InitSecondSplitWrite:
inst->split2ndAccess = true;
assert(inst->split2ndAddr != 0);
- write(inst, inst->split2ndAddr, inst->split2ndData,
- inst->split2ndFlags, NULL);
+ write(inst, &inst->split2ndData, inst->totalSize,
+ inst->split2ndAddr, inst->split2ndFlags, NULL);
break;
if (inst->splitFinishCnt == 2) {
cache_req->memReq->setVirt(0/*inst->tid*/,
inst->getMemAddr(),
- inst->splitTotalSize,
+ inst->totalSize,
0,
0);
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);
-}
-
/** Returns a specific port. */
Port *getPort(const std::string &if_name, int idx);
- template <class T>
- Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
+ Fault read(DynInstPtr inst, Addr addr,
+ uint8_t *data, unsigned size, unsigned flags);
- template <class T>
- Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags,
- uint64_t *res);
+ Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *res);
Fault doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
int flags, TheISA::TLB::Mode tlb_mode);
std::vector<ThreadID> tids;
/** CPU read function, forwards read to LSQ. */
- template <class T>
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,
data, load_idx);
}
/** CPU write function, forwards write to LSQ. */
- template <class T>
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,
data, store_idx);
/** Executes a read operation, using the load specified at the load
* index.
*/
- template <class T>
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
* index.
*/
- template <class T>
Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
- T &data, int store_idx);
+ uint8_t *data, int store_idx);
/** The CPU pointer. */
O3CPU *cpu;
};
template <class Impl>
-template <class T>
Fault
LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
- T &data, int load_idx)
+ uint8_t *data, int load_idx)
{
ThreadID tid = req->threadId();
}
template <class Impl>
-template <class T>
Fault
LSQ<Impl>::write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
- T &data, int store_idx)
+ uint8_t *data, int store_idx)
{
ThreadID tid = req->threadId();
public:
/** Executes the load at the given index. */
- template <class T>
- Fault read(Request *req, Request *sreqLow, Request *sreqHigh, T &data,
- int load_idx);
+ Fault read(Request *req, Request *sreqLow, Request *sreqHigh,
+ uint8_t *data, int load_idx);
/** Executes the store at the given index. */
- template <class T>
- Fault write(Request *req, Request *sreqLow, Request *sreqHigh, T &data,
- int store_idx);
+ Fault write(Request *req, Request *sreqLow, Request *sreqHigh,
+ uint8_t *data, int store_idx);
/** Returns the index of the head load instruction. */
int getLoadHead() { return loadHead; }
};
template <class Impl>
-template <class T>
Fault
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];
// Get shift amount for offset into the store's data.
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);
load_inst->memData = new uint8_t[64];
}
template <class Impl>
-template <class T>
Fault
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);
storeQueue[store_idx].req = req;
storeQueue[store_idx].sreqLow = sreqLow;
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
// a store request has been split, sreqLow and sreqHigh will be non-null.
if (TheISA::HasUnalignedMemAcc && sreqLow) {
storeQueue[store_idx].isSplit = true;
}
- assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
- T gData = htog(data);
- memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
+ memcpy(storeQueue[store_idx].data, data, size);
// This function only writes the data to the store queue, so no fault
// can happen here.
}
-template <class T>
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
Request *req = &data_read_req;
//The block size of our peer.
unsigned blockSize = dcachePort.peerBlockSize();
//The size of the data we're trying to read.
- int dataSize = sizeof(T);
-
- uint8_t * dataPtr = (uint8_t *)&data;
+ int fullSize = size;
//The address of the second part of this access if it needs to be split
//across a cache line boundary.
- Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+ Addr secondAddr = roundDown(addr + size - 1, blockSize);
- if(secondAddr > addr)
- dataSize = secondAddr - addr;
+ if (secondAddr > addr)
+ size = secondAddr - addr;
dcache_latency = 0;
- while(1) {
- req->setVirt(0, addr, dataSize, flags, thread->readPC());
+ while (1) {
+ req->setVirt(0, addr, size, flags, thread->readPC());
// translate to physical address
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
Packet pkt = Packet(req,
req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
Packet::Broadcast);
- pkt.dataStatic(dataPtr);
+ pkt.dataStatic(data);
if (req->isMmapedIpr())
dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);
//If we don't need to access a second cache line, stop now.
if (secondAddr <= addr)
{
- data = gtoh(data);
- if (traceData) {
- traceData->setData(data);
- }
if (req->isLocked() && fault == NoFault) {
assert(!locked);
locked = true;
*/
//Move the pointer we're reading into to the correct location.
- dataPtr += dataSize;
+ data += size;
//Adjust the size to get the remaining bytes.
- dataSize = addr + sizeof(T) - secondAddr;
+ size = addr + fullSize - secondAddr;
//And access the right address.
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
template
}
-template <class T>
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
Request *req = &data_write_req;
if (traceData) {
traceData->setAddr(addr);
- traceData->setData(data);
}
- data = htog(data);
-
//The block size of our peer.
unsigned blockSize = dcachePort.peerBlockSize();
//The size of the data we're trying to read.
- int dataSize = sizeof(T);
-
- uint8_t * dataPtr = (uint8_t *)&data;
+ int fullSize = size;
//The address of the second part of this access if it needs to be split
//across a cache line boundary.
- Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+ Addr secondAddr = roundDown(addr + size - 1, blockSize);
if(secondAddr > addr)
- dataSize = secondAddr - addr;
+ size = secondAddr - addr;
dcache_latency = 0;
while(1) {
- req->setVirt(0, addr, dataSize, flags, thread->readPC());
+ req->setVirt(0, addr, size, flags, thread->readPC());
// translate to physical address
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) {
Packet pkt = Packet(req, cmd, Packet::Broadcast);
- pkt.dataStatic(dataPtr);
+ pkt.dataStatic(data);
if (req->isMmapedIpr()) {
dcache_latency +=
if (req->isSwap()) {
assert(res);
- *res = pkt.get<T>();
+ memcpy(res, pkt.getPtr<uint8_t>(), fullSize);
}
}
*/
//Move the pointer we're reading into to the correct location.
- dataPtr += dataSize;
+ data += size;
//Adjust the size to get the remaining bytes.
- dataSize = addr + sizeof(T) - secondAddr;
+ size = addr + fullSize - secondAddr;
//And access the right address.
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
template
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
+ Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
template <class T>
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
* debugging).
pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
}
-template <class T>
Fault
-TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
+TimingSimpleCPU::readBytes(Addr addr, uint8_t *data,
+ unsigned size, unsigned flags)
{
Fault fault;
const int asid = 0;
const ThreadID tid = 0;
const Addr pc = thread->readPC();
unsigned block_size = dcachePort.peerBlockSize();
- int data_size = sizeof(T);
BaseTLB::Mode mode = BaseTLB::Read;
if (traceData) {
traceData->setAddr(addr);
}
- RequestPtr req = new Request(asid, addr, data_size,
+ RequestPtr req = new Request(asid, addr, size,
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);
_status = DTBWaitResponse;
req->splitOnVaddr(split_addr, req1, req2);
WholeTranslationState *state =
- new WholeTranslationState(req, req1, req2, (uint8_t *)(new T),
+ new WholeTranslationState(req, req1, req2, new uint8_t[size],
NULL, mode);
DataTranslation<TimingSimpleCPU> *trans1 =
new DataTranslation<TimingSimpleCPU>(this, state, 0);
thread->dtb->translateTiming(req2, tc, trans2, mode);
} else {
WholeTranslationState *state =
- new WholeTranslationState(req, (uint8_t *)(new T), NULL, mode);
+ new WholeTranslationState(req, new uint8_t[size], NULL, mode);
DataTranslation<TimingSimpleCPU> *translation
= new DataTranslation<TimingSimpleCPU>(this, state);
thread->dtb->translateTiming(req, tc, translation, mode);
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
template
return dcache_pkt == NULL;
}
-template <class T>
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 ThreadID tid = 0;
const Addr pc = thread->readPC();
unsigned block_size = dcachePort.peerBlockSize();
- int data_size = sizeof(T);
BaseTLB::Mode mode = BaseTLB::Write;
if (traceData) {
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);
- 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);
- T *dataP = new T;
- *dataP = TheISA::htog(data);
_status = DTBWaitResponse;
if (split_addr > addr) {
RequestPtr req1, req2;
req->splitOnVaddr(split_addr, req1, req2);
WholeTranslationState *state =
- new WholeTranslationState(req, req1, req2, (uint8_t *)dataP,
- res, mode);
+ new WholeTranslationState(req, req1, req2, data, res, mode);
DataTranslation<TimingSimpleCPU> *trans1 =
new DataTranslation<TimingSimpleCPU>(this, state, 0);
DataTranslation<TimingSimpleCPU> *trans2 =
thread->dtb->translateTiming(req2, tc, trans2, mode);
} else {
WholeTranslationState *state =
- new WholeTranslationState(req, (uint8_t *)dataP, res, mode);
+ new WholeTranslationState(req, data, res, mode);
DataTranslation<TimingSimpleCPU> *translation =
new DataTranslation<TimingSimpleCPU>(this, state);
thread->dtb->translateTiming(req, tc, translation, mode);
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
template
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
+ Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
template <class T>
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 sendFetch(Fault fault, RequestPtr req, ThreadContext *tc);
void completeIfetch(PacketPtr );
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;
FetchEvent fetchEvent;