⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loadstoreunit.cpp

📁 ppc750 system design simulator using system c
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		}#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 + -