📄 loadstoreunit.cpp
字号:
}#endif } if(loadWaitingForAck && (Dummy<bool>) inDCacheAck) { loadWaitingForAck = false; switch(stage2.load.state) { case MSB_ACCESS: outDCacheReq = false;#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": End of MSB access" << endl;#endif stage2.load.state = LSB_ACCESS; break; case NORMAL_ACCESS: case LSB_ACCESS: outDCacheReq = false; stage2.load.valid = false;#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": Removing a load from load queue" << endl; cout << name() << ": Load Queue is not stalled" << endl; }#endif break; }#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_response"); trace_file->Value("number", stage2.load.dbgInstructionCounter); trace_file->Value("pc", stage2.load.dbgProgramCounter); trace_file->End("dcache_response"); }#endif } #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << stage2.storeQueue; cout << "stage1.valid = " << stage1.valid << endl; cout << "load waiting for ack = " << loadWaitingForAck << endl; cout << "store waiting for ack = " << storeWaitingForAck << endl; }#endif if(inBranchFinished) { if(inMispredictedBranch) Flush(); DecrementBranchCounter(); }#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << "stage1.valid = " << stage1.valid << endl; cout << "stage1.operation.ident = " << stage1.operation.ident << endl; cout << "stage1.operation.write = " << stage1.operation.write << endl; }#endif stage2.storeQueue.Shift(); #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << "store queue after shifting :" << endl << stage2.storeQueue;#endif /* Shift the pipeline if we can do it */ if(stage1.valid) { if(!stage1.operation.write) { /* Load */#ifdef DEBUG if(stage2.load.valid) { cout << ": Can't add a load to load queue (tag = " << (int) stage1.tags.tag << ") (" << stage1.dbgInstructionCounter << ") "; ppc_disassemble_to_stream(stage1.dbgInstruction, stage1.dbgProgramCounter, stdout); cout << endl; ABORT(); }#endif stage2.load.addr = stage1.addr; stage2.load.operation = stage1.operation; stage2.load.tags = stage1.tags; stage2.load.branchCounter = stage1.branchCounter; stage2.load.valid = true; stage2.storeQueue.SetLoadDependency(stage2.load.tags.tag, stage2.load.addr, stage2.load.operation.size); stage2.load.state = NORMAL_ACCESS; stage1.valid = false;#if defined(DEBUG) || defined(TRACE) stage2.load.dbgInstructionCounter = stage1.dbgInstructionCounter; stage2.load.dbgProgramCounter = stage1.dbgProgramCounter; stage2.load.dbgInstruction = stage1.dbgInstruction;#endif } else { /* Store */#ifdef DEBUG if(stage2.storeQueue.GetFreeSpace() <= 0) { cout << name() << ": Can't add a store to store queue (tag = " << (int) stage1.tags.tag << ") (" << stage1.dbgInstructionCounter << ") "; ppc_disassemble_to_stream(stage1.dbgInstruction, stage1.dbgProgramCounter, stdout); cout << endl; ABORT(); }#endif /* Filling of the store queue */ StoreQueueEntry *entry = stage2.storeQueue.Allocate(); entry->addr = stage1.addr; entry->operation = stage1.operation; entry->tags = stage1.tags; entry->data = stage1.data; entry->branchCounter = stage1.branchCounter; entry->valid = false; entry->dependentLoadTag = -1; entry->state = NORMAL_ACCESS;#if defined(DEBUG) || defined(TRACE) entry->dbgInstructionCounter = stage1.dbgInstructionCounter; entry->dbgProgramCounter = stage1.dbgProgramCounter; entry->dbgInstruction = stage1.dbgInstruction;#endif stage1.valid = false;#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": Adding store to store queue (tag = " << (int) stage1.tags.tag << ") (" << stage1.dbgInstructionCounter << ") "; ppc_disassemble_to_stream(stage1.dbgInstruction, stage1.dbgProgramCounter, stdout); cout << endl; cout << stage2.storeQueue; }#endif } } outEmpty = !stage1.valid && !stage2.load.valid && stage2.storeQueue.Empty();}void LoadStoreUnit::Load(){ /* Do the data cache request */ outDCacheReq = true; /* There is one or two data cache access depending on the data alignment */ /* If the data access crosses a cache line boundary there is two data cache access */ /* In most cases there is only one data cache access */ switch(stage2.load.state) { case NORMAL_ACCESS: if(Misalignment(stage2.load.addr, stage2.load.operation.size) && CrossLineBoundary(stage2.load.addr, stage2.load.operation.size)) { /* Data cache access crosses a cache line boundary */ /* Start the data cache access with the most significative bytes */ stage2.load.state = MSB_ACCESS; UInt32 size = linesize - (stage2.load.addr % linesize); outDCacheSize = size;#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_request"); trace_file->Value("addr", stage2.load.addr); trace_file->Value("size", size); trace_file->Value("write", false); trace_file->End("dcache_request"); }#endif } else { /* Data cache access is well aligned */ outDCacheSize = stage2.load.operation.size;#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_request"); trace_file->Value("addr", stage2.load.addr); trace_file->Value("size", stage2.load.operation.size); trace_file->Value("write", false); trace_file->End("dcache_request"); }#endif } outDCacheAddr = stage2.load.addr; break; case LSB_ACCESS: { /* We previously access to the most significative bytes */ /* Now we do the data cache access for the less significative bytes */ UInt32 addr = (stage2.load.addr - stage2.load.addr % linesize) + linesize;; outDCacheAddr = addr; UInt32 size = stage2.load.operation.size - (linesize - (stage2.load.addr % linesize)); outDCacheSize = size;#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_request"); trace_file->Value("addr", stage2.load.addr); trace_file->Value("size", size); trace_file->Value("write", false); trace_file->End("dcache_request"); }#endif } break; } outDCacheWrite = false;}void LoadStoreUnit::Store(StoreQueueEntry *entry){ DataArray<lsu2dcache> data; outDCacheReq = true; outDCacheWrite = true; switch(entry->operation.ident) { case ID_DCBZ: outDCacheAddr = entry->addr; outDCacheSize = entry->operation.size; outDCacheZeroBlock = true; break; default: { UInt64 dataToWrite; /* There is one or two data cache access depending on the data alignment */ /* If the data access crosses a cache line boundary there is two data cache access */ /* In most cases there is only one data cache access */ switch(entry->state) { case NORMAL_ACCESS: if(Misalignment(entry->addr, entry->operation.size) && CrossLineBoundary(entry->addr, entry->operation.size)) { /* Data cache access crosses a cache line boundary */ /* Start the data cache access with the most significative bytes */ entry->state = MSB_ACCESS; UInt32 size = linesize - (entry->addr % linesize); outDCacheSize = size; #ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_access"); trace_file->Value("addr", entry->addr); trace_file->Value("size", size); trace_file->Value("write", true); trace_file->End("dcache_access"); }#endif dataToWrite = entry->data; } else { /* Data cache access is well aligned */ outDCacheSize = entry->operation.size; dataToWrite = entry->data;#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_access"); trace_file->Value("addr", entry->addr); trace_file->Value("size", entry->operation.size); trace_file->Value("write", true); trace_file->End("dcache_access"); }#endif } outDCacheAddr = entry->addr; break; case LSB_ACCESS: { /* We previously access to the most significative bytes */ /* Now we do the data cache access for the less significative bytes */ UInt32 addr = (entry->addr - entry->addr % linesize) + linesize; outDCacheAddr = addr; UInt32 size = entry->operation.size - (linesize - (entry->addr % linesize)); outDCacheSize = size; dataToWrite = entry->data << (8 * (linesize - entry->addr % linesize));#ifdef TRACE if(Trace(TraceLoadStoreUnit)) { trace_file->Begin("dcache_access"); trace_file->Value("addr", addr); trace_file->Value("size", size); trace_file->Value("write", true); trace_file->End("dcache_access"); }#endif } break; } switch(entry->operation.size) { case 1: data[0] = dataToWrite; break; case 2: data[0] = dataToWrite >> 8; data[1] = dataToWrite; break; case 4: if(entry->operation.floatingPoint) { /* 64 bits Floating point data must be converted to a 32 bits floating point data */ double d = *(double *) &dataToWrite; float f = d; UInt32 data32 = *(UInt32 *) &f; data[0] = data32 >> 24; data[1] = data32 >> 16; data[2] = data32 >> 8; data[3] = data32; } else { data[0] = dataToWrite >> 24; data[1] = dataToWrite >> 16; data[2] = dataToWrite >> 8; data[3] = dataToWrite; } break; case 8: data[0] = dataToWrite >> 56; data[1] = dataToWrite >> 48; data[2] = dataToWrite >> 40; data[3] = dataToWrite >> 32; data[4] = dataToWrite >> 24; data[5] = dataToWrite >> 16; data[6] = dataToWrite >> 8; data[7] = dataToWrite; break; } outDCacheData = data; outDCacheZeroBlock = false; } }}void LoadStoreUnit::WriteBack(){ int i; #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": Write Back" << endl;#endif for(i = 0; i < nMemoryWriteBackPorts; i++) { if((Dummy<bool>) inWriteBack[i]) { StoreQueueEntry *entry = stage2.storeQueue.GetOldest(); if(!loadWaitingForAck && !storeWaitingForAck && entry && entry->tags.tag == inWriteBackTag[i]) { entry->valid = true; Store(entry); #ifdef DEBUG if(Debug(DebugLoadStoreUnit)) { cout << name() << ": Writing " << entry->operation.size << " bytes (" << entry->data << ") at "; WriteHex(cout, entry->addr); cout << endl; }#endif storeWaitingForAck = true; } else {#ifdef DEBUG if(Debug(DebugLoadStoreUnit)) cout << name() << ": Validating a store (tag = " << (int) inWriteBackTag[i] << ")" << endl;#endif stage2.storeQueue.Validate(inWriteBackTag[i]); } } } }void LoadStoreUnit::DecrementBranchCounter(){ if(stage1.valid) if(stage1.branchCounter > 0) stage1.branchCounter--; if(stage2.load.valid) if(stage2.load.branchCounter > 0) stage2.load.branchCounter--; stage2.storeQueue.DecrementBranchCounter();}void LoadStoreUnit::Flush(){ if(stage1.valid) if(stage1.branchCounter > 0) stage1.valid = false; if(stage2.load.valid) if(stage2.load.branchCounter > 0) stage2.load.valid = false; stage2.storeQueue.Flush();}void LoadStoreUnit::Reset(){ loadWaitingForAck = 0; storeWaitingForAck = 0; stage1.valid = false; stage1.state = 0; memset(&stage1.operation, 0, sizeof(stage1.operation)); memset(&stage1.tags, -1, sizeof(stage1.tags)); stage1.addr = 0; stage1.data = 0; stage1.branchCounter = 0; stage2.load.valid = false; stage2.load.state = 0; memset(&stage2.load.operation, 0, sizeof(stage2.load.operation)); memset(&stage2.load.tags, -1, sizeof(stage2.load.tags)); stage2.load.addr = 0; stage2.load.branchCounter = 0; stage2.storeQueue.Reset();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -