Made the "data" field of store queue entries into a character array. It's sized to match an IntReg which was what it used to be, but we might want to make it something architecture independent. All data is now endian converted before entering the store queue entries which simplifies store to load forwarding in "trans endian" simulations, and makes twin memory ops work.

src/cpu/o3/lsq_unit.hh:
src/cpu/o3/lsq_unit_impl.hh:
    fixed twin memory operations.

--HG--
extra : convert_revision : 8fb97f98e285cd22413e06e146fa82392ac2a590
This commit is contained in:
Gabe Black 2007-04-03 22:53:26 +00:00
parent 30f101881f
commit 10fe8b05db
2 changed files with 17 additions and 31 deletions

View file

@ -297,15 +297,19 @@ class LSQUnit {
struct SQEntry {
/** Constructs an empty store queue entry. */
SQEntry()
: inst(NULL), req(NULL), size(0), data(0),
: inst(NULL), req(NULL), size(0),
canWB(0), committed(0), completed(0)
{ }
{
bzero(data, sizeof(data));
}
/** Constructs a store queue entry for a given instruction. */
SQEntry(DynInstPtr &_inst)
: inst(_inst), req(NULL), size(0), data(0),
: inst(_inst), req(NULL), size(0),
canWB(0), committed(0), completed(0)
{ }
{
bzero(data, sizeof(data));
}
/** The store instruction. */
DynInstPtr inst;
@ -314,7 +318,7 @@ class LSQUnit {
/** The size of the store. */
int size;
/** The store data. */
IntReg data;
char data[sizeof(IntReg)];
/** Whether or not the store can writeback. */
bool canWB;
/** Whether or not the store is committed. */
@ -562,22 +566,14 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
if ((store_has_lower_limit && store_has_upper_limit)) {
// Get shift amount for offset into the store's data.
int shift_amt = req->getVaddr() & (store_size - 1);
// @todo: Magic number, assumes byte addressing
shift_amt = shift_amt << 3;
// Cast this to type T?
data = storeQueue[store_idx].data >> shift_amt;
// When the data comes from the store queue entry, it's in host
// order. When it gets sent to the load, it needs to be in guest
// order so when the load converts it again, it ends up back
// in host order like the inst expects.
data = TheISA::htog(data);
memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T));
assert(!load_inst->memData);
load_inst->memData = new uint8_t[64];
memcpy(load_inst->memData, &data, req->getSize());
memcpy(load_inst->memData,
storeQueue[store_idx].data + shift_amt, req->getSize());
DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
"addr %#x, data %#x\n",
@ -724,7 +720,10 @@ LSQUnit<Impl>::write(Request *req, T &data, int store_idx)
storeQueue[store_idx].req = req;
storeQueue[store_idx].size = sizeof(T);
storeQueue[store_idx].data = data;
assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
T gData = htog(data);
memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
// This function only writes the data to the store queue, so no fault
// can happen here.

View file

@ -641,20 +641,7 @@ LSQUnit<Impl>::writebackStores()
assert(!inst->memData);
inst->memData = new uint8_t[64];
TheISA::IntReg convertedData =
TheISA::htog(storeQueue[storeWBIdx].data);
//FIXME This is a hack to get SPARC working. It, along with endianness
//in the memory system in general, need to be straightened out more
//formally. The problem is that the data's endianness is swapped when
//it's in the 64 bit data field in the store queue. The data that you
//want won't start at the beginning of the field anymore unless it was
//a 64 bit access.
memcpy(inst->memData,
(uint8_t *)&convertedData +
(TheISA::ByteOrderDiffers ?
(sizeof(TheISA::IntReg) - req->getSize()) : 0),
req->getSize());
memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize());
PacketPtr data_pkt = new Packet(req, MemCmd::WriteReq,
Packet::Broadcast);