📄 loadstoreunit.cpp
字号:
/*************************************************************************** LoadStoreUnit.cpp - description ------------------- begin : Tue Apr 24 2001 copyright : (C) 2001 Universite Paris Sud and CEA author : Gilles Mouchard email : gilles.mouchard@lri.fr, gilles.mouchard@.cea.fr ***************************************************************************/#include <LoadStoreUnit.h>bool LoadStoreUnit::Misalignment(UInt32 addr, int size){ return (addr % size) != 0;}bool LoadStoreUnit::CrossLineBoundary(UInt32 addr, int size){ return linesize - (addr % linesize) < size;}void LoadStoreUnit::OnFrontEdge(){ bool finished = false; bool resultValid = false; #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << stage2.storeQueue; cout << "load waiting for ack = " << loadWaitingForAck << endl; cout << "store waiting for ack = " << storeWaitingForAck << endl; cout << "stage1.valid = " << stage1.valid << endl; cout << "stage2.load.valid = " << stage2.load.valid << endl; }#endif /* Data Cache Access */ /* See if we are waiting for an instruction accessing to the data cache */ if(!loadWaitingForAck && !storeWaitingForAck) { /* We are free to access to the data cache */ /* See if the load can be done before some store instructions by checking the dependencies */ if(stage2.load.valid && !stage2.storeQueue.HasLoadDependency(stage2.load.tags.tag)) { /* Load */#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": Loading " << (int) stage2.load.operation.size << " bytes at "; WriteHex(cout, stage2.load.addr); cout << endl; }#endif Load(); /* Make the load/store unit to wait for the load to complete into the the data cache */ loadWaitingForAck = true; } else { /* Store */ /* Get a the oldest store into the store queue */ StoreQueueEntry *entry = stage2.storeQueue.GetOldestValid(); #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": entry = " << entry << endl;#endif if(entry) { Store(entry); /* Make the load/store to wait for the store to complete */ storeWaitingForAck = true;#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": Storing " << entry->data << " at "; WriteHex(cout, entry->addr); cout << endl; }#endif } } } /* Effective Address Calculation */ bool storeQueueStalled = stage2.storeQueue.GetFreeSpace() <= 0; bool loadQueueStalled = stage2.load.valid || loadWaitingForAck; if(inDispatched) { /* A new load/store instruction has been started */ const LoadStoreOperation& operation = inOperation; const LoadStoreOperands& operands = inOperands; const LoadStoreTags& tags = inTags;#if defined(DEBUG) || defined(TRACE) UInt32 dbgInstructionCounter = inInstructionCounter; UInt32 dbgProgramCounter = inProgramCounter; UInt32 dbgInstruction = inInstruction;#endif#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": " << (operation.write ? "store" : "load") << " dispatched (tag = " << (int) tags.tag << ") (" << dbgInstructionCounter << ") "; ppc_disassemble_to_stream(dbgInstruction, dbgProgramCounter, stdout); cout << endl; cout << name() << ": Computing Effective Address" << endl; cout << name() << ": (RS) = "; WriteHex(cout, operands.data0); cout << ", (RA) = "; WriteHex(cout, operands.data1); cout << ", (RB)/immed = "; WriteHex(cout, operands.data2); cout << endl; if(operation.nullRA) cout << name() << ": RA = 0" << endl; }#endif /* Effective Address Calculation */ /* operands.data[0] -> (RS) */ /* operands.data[1] -> (RA) */ /* operands.data[2] -> (RB)/immed */ UInt32 EA = operation.nullRA ? operands.data2 : operands.data1 + operands.data2; stage1.tags = tags; stage1.addr = EA; stage1.operation = operation; if(stage1.operation.ident == ID_DCBZ) { stage1.operation.size = linesize; } stage1.branchCounter = inBranchCounter; stage1.valid = true; stage1.data = operands.data0;#if defined(DEBUG) || defined(TRACE) stage1.dbgInstructionCounter = dbgInstructionCounter; stage1.dbgProgramCounter = dbgProgramCounter; stage1.dbgInstruction = dbgInstruction;#endif #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": EA = "; WriteHex(cout, EA); cout << endl; }#endif#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("execute"); trace_file->Value("unit", "load/store"); trace_file->Value("number", dbgInstructionCounter); trace_file->Value("pc", dbgInstructionCounter); trace_file->Value("write", operation.write); trace_file->Value("addr", EA); trace_file->End("execute"); }#endif if(stage1.operation.write) {#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": finishing a store (tag = " << (int) stage1.tags.tag << ") (" << stage1.dbgInstructionCounter << ") "; ppc_disassemble_to_stream(stage1.dbgInstruction, stage1.dbgProgramCounter, stdout); cout << endl; }#endif finished = true; outTag[0] = stage1.tags.tag; storeQueueStalled = stage2.storeQueue.GetFreeSpace() <= 1; } else { loadQueueStalled = true; } /* Update (RA) if necessary */ if(tags.resultTags[1] >= 0) { resultValid = true; outResultData[1] = EA; outResultTag[1] = tags.resultTags[1]; } } outFinished[0] = finished; outFinished[1] = false; outResultValid[0] = false; outFloatingPointResultValid = false; outResultValid[1] = resultValid;#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { if(storeQueueStalled) cout << name() << ": Store Queue stalled" << endl; if(stage2.load.valid) cout << name() << ": Load Queue stalled" << endl; }#endif #ifdef TRACE if(Trace(TraceLoadStoreUnit)) { stage2.storeQueue.Trace(); }#endif outStoreQueueStalled = storeQueueStalled; outLoadQueueStalled = loadQueueStalled;}void LoadStoreUnit::Forward(){ if(loadWaitingForAck && (Dummy<bool>) inDCacheAck) { if(stage2.load.valid) { /* Load */ /* Forward of the load result */ UInt64 result;#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": Getting data from Data Cache" << endl;#endif switch(stage2.load.state) { case NORMAL_ACCESS: stage2.load.data = inDCacheData; break; case MSB_ACCESS: { DataArray<lsu2dcache> data = inDCacheData; UInt32 size = linesize - (stage2.load.addr % linesize); int i; #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": MSB =";#endif for(i = 0; i < size; i++) { stage2.load.data[i] = data[i];#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << " "; WriteHex(cout, stage2.load.data[i]); }#endif }#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << endl;#endif } break; case LSB_ACCESS: { DataArray<lsu2dcache> data = inDCacheData; UInt32 offset = linesize - (stage2.load.addr % linesize); UInt32 size = stage2.load.operation.size - offset; int i; #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": LSB =";#endif for(i = 0; i < size; i++) { stage2.load.data[offset + i] = data[i];#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << " "; WriteHex(cout, data[i]); }#endif }#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << endl;#endif } break; } switch(stage2.load.state) { case NORMAL_ACCESS: case LSB_ACCESS: if(stage2.load.operation.algebraic) { /* Sign extension of the load result */ switch(stage2.load.operation.size) { case 1: result = (SInt32) (SInt8) stage2.load.data[0]; break; case 2: result = (SInt32) (SInt16) (stage2.load.data[0] << 8) | (stage2.load.data[1]); break; case 4: result = (stage2.load.data[0] << 24) | (stage2.load.data[1] << 16) | (stage2.load.data[2] << 8) | (stage2.load.data[3]); break; default: cout << name() << ": size is not valid" << endl; ABORT(); } } else { /* zero extension of the load result */ switch(stage2.load.operation.size) { case 1: result = stage2.load.data[0]; break; case 2: result = (stage2.load.data[0] << 8) | (stage2.load.data[1]); break; case 4: if(stage2.load.operation.floatingPoint) { UInt32 result32 = (stage2.load.data[0] << 24) | (stage2.load.data[1] << 16) | (stage2.load.data[2] << 8) | (stage2.load.data[3]); float fresult = *(float *) &result32; double dresult = fresult; result = *(UInt64 *) &dresult; } else { result = (stage2.load.data[0] << 24) | (stage2.load.data[1] << 16) | (stage2.load.data[2] << 8) | (stage2.load.data[3]); } break; case 8: result = ((UInt64) stage2.load.data[0] << 56) | ((UInt64) stage2.load.data[1] << 48) | ((UInt64) stage2.load.data[2] << 40) | ((UInt64) stage2.load.data[3] << 32) | ((UInt64) stage2.load.data[4] << 24) | ((UInt64) stage2.load.data[5] << 16) | ((UInt64) stage2.load.data[6] << 8) | ((UInt64) stage2.load.data[7]); break; } } #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": producing "; WriteHex(cout, result); cout << endl; cout << name() << ": finishing a load (tag = " << (int) stage2.load.tags.tag << ") (" << stage2.load.dbgInstructionCounter << ") "; ppc_disassemble_to_stream(stage2.load.dbgInstruction, stage2.load.dbgProgramCounter, stdout); cout << endl; cout << name() << ": Load Queue is not stalled" << endl; }#endif /* Make the result available to other units */ if(stage2.load.operation.floatingPoint) { outFloatingPointResultValid = true; outResultValid[0] = false; outFloatingPointResultData = result; } else { outFloatingPointResultValid = false; outResultValid[0] = true; outResultData[0] = result; } outResultTag[0] = stage2.load.tags.resultTags[0]; outFinished[1] = true; outTag[1] = stage2.load.tags.tag; outLoadQueueStalled = false; break; } } } if(storeWaitingForAck && (Dummy<bool>) inDCacheAck) { StoreQueueEntry *entry = stage2.storeQueue.GetOldest(); outStoreQueueStalled = entry->state == MSB_ACCESS; }} void LoadStoreUnit::OnFallingEdge(){ if(storeWaitingForAck && (Dummy<bool>) inDCacheAck) { StoreQueueEntry *entry = stage2.storeQueue.GetOldest(); storeWaitingForAck = false; switch(entry->state) { case MSB_ACCESS: outDCacheReq = false;#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": End of MSB access" << endl;#endif entry->state = LSB_ACCESS; break; case NORMAL_ACCESS: case LSB_ACCESS: outDCacheReq = false; stage2.storeQueue.ReleaseTail();#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": Removing a store from store queue" << endl; cout << name() << ": Store Queue is not stalled" << endl; }#endif break; }#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_response"); trace_file->Value("number", entry->dbgInstructionCounter); trace_file->Value("pc", entry->dbgProgramCounter); trace_file->End("dcache_response");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -