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

📄 mipssimulator.cpp

📁 mips处理器指令仿真器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// MIPSSimulator.cpp : implementation file
//

#include "stdafx.h"
#include "pipeline.h"
#include "MIPSSimulator.h"
#include "Error.h"

#include <malloc.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CString MIPSStage[] =
{
	"IF", "ID", "EX", "MEM", "WB", "STALL", "IDLE", "COMPLETE"
};

/////////////////////////////////////////////////////////
// Global
CMIPSSimulator simulator;

/////////////////////////////////////////////////////////
// CLASS CMIPSSIMULATOR
/////////////////////////////////////////////////////////
// Construction
CMIPSSimulator::CMIPSSimulator()
{
	m_pInsts = NULL;
	m_pExecInsts = new CExecInst(1);
	data = NULL;

	/****************************************
	 * Configurations
	 ****************************************/
	m_bForwardingEnable = TRUE;
	m_nBranchMethod = kFreeze;
	// delays
	m_nAddDelay = 1;
	m_nMulDelay = 5;
	m_nDivDelay = 19;
	// ALU numbers
	m_nAddNum = 1;
	m_nMulNum = 1;
	m_nDivNum = 1;
	// is ALU pipelined
	m_bAddPipelined = TRUE;
	m_bMulPipelined = TRUE;
	m_bDivPipelined = FALSE;
	// memory
	m_nMemSize = 0x1000;
	m_nDataSize = 0x100;
	m_bBigEnding = FALSE;

	Reset();
}

CMIPSSimulator::~CMIPSSimulator()
{
	if( m_pExecInsts ) delete m_pExecInsts;
	if( m_pInsts ) delete m_pInsts;
	if( data ) free( data );
	if( data_bak ) free( data_bak );
	if( m_TraceFile.m_hFile != CFile::hFileNull )
		m_TraceFile.Close();
}

void CMIPSSimulator::ResetProgram()
{
	m_bTrace = FALSE;
	m_bNewStep = FALSE;
	m_nState = kNone;
	// Program Counter
	PC = m_nDataSize;

	if( m_pExecInsts->next ) { 
		delete m_pExecInsts->next; 
		m_pExecInsts->next = NULL;
	}
	if( m_pInsts ) { delete m_pInsts; m_pInsts = NULL; }
	memset( &STAT, 0, sizeof(STAT) );
}

void CMIPSSimulator::Reset()
{
	m_bTrace = FALSE;
	m_bNewStep = FALSE;
	m_nState = kNone;
	// Program Counter
	PC = m_nDataSize;

	if( m_pExecInsts->next ) { 
		delete m_pExecInsts->next; 
		m_pExecInsts->next = NULL;
	}
	if( m_pInsts ) { delete m_pInsts; m_pInsts = NULL; }
	if( data ) memset( data, 0, m_nDataSize );
	memset( reg, 0, sizeof(reg) );
	memset( &STAT, 0, sizeof(STAT) );

	ClearIFIDReg();
	ClearIDEXReg();
	ClearEXMEMReg();
	ClearMUL_EXMEMReg();
	ClearDIV_EXMEMReg();
	ClearMEMWBReg();
	ClearMUL_MEMWBReg();
	ClearDIV_MEMWBReg();
}

void CMIPSSimulator::CreateDataMem()
{
	if( data == NULL ) {
		data = (int*)malloc( m_nDataSize );
		memset( data, 0, m_nDataSize );
	} else {
		UINT len = _msize( data );
		if( m_nDataSize != len )
			data = (int*)realloc( data, m_nDataSize );
		if( len < m_nDataSize )
			memset( &data[len/4], 0, m_nDataSize - len );
	}

	if( m_pInsts ) {
		PC = m_nDataSize;
		// asign addresses
		AsignAddress();
		// Resolve labels in J-TYPE instructions
		ResolveLabels();
	}
}

void CMIPSSimulator::ClearDataMem()
{
	memset( data, 0, _msize(data) );
}

void CMIPSSimulator::FreeDataMem()
{
	free( data ); data = NULL;
}

void CMIPSSimulator::BackupMem()
{
	data_bak = (int*)realloc(data_bak, _msize(data));
	memcpy( data_bak, data, _msize(data) );
}

void CMIPSSimulator::RollBackMem()
{
	ASSERT( _msize(data) == _msize(data_bak) );
	memcpy( data, data_bak, _msize(data) );
}

void CMIPSSimulator::BackupReg()
{
	for( int i = 0; i < 32; i++ )
		reg_bak[i] = reg[i].content;
}

void CMIPSSimulator::RollBackReg()
{
	CSlot slot;
	for( int i = 0; i < 32; i++ ) {
		slot.content = reg_bak[i];
		reg[i] = slot;
	}
}

BOOL CMIPSSimulator::IsReadyForExec()
{
	if( data && m_pInsts && m_pInsts->m_instList.GetCount() )
		return TRUE;
	return FALSE;
}

BOOL CMIPSSimulator::LoadInstFromFile( LPCTSTR pathname )
{
	CFile cfile;
	// open the file
	try {
		cfile.Open( pathname, CFile::modeRead );
	} catch( CFileException& ) {
		CString temp;
		temp.Format( "failed to open\n%s", pathname );
		AfxMessageBox( temp );
		return FALSE;
	}
	// read the whole content
	CString strBuf;
	char buf[ 4100 ];
	int len = 0;
	try {
		while( (len = cfile.Read(buf, 4096)) > 0 ) {
			buf[len] = '\0';
			strBuf += (CString)buf;
		}
		strBuf += "\r\n";
	} catch( CFileException& ) {
		CString temp;
		temp.Format( "error occurs while reading\n%s", pathname );
		AfxMessageBox( temp );
		cfile.Close();
		return FALSE;
	}
	cfile.Close();// close the file
	try {
		// construct the Instructions object
		m_pInsts = new CInstructions( strBuf );
		if( m_pInsts->m_instList.IsEmpty() ) {
			delete m_pInsts; m_pInsts = NULL;
			return FALSE;
		}
		// asign addresses
		AsignAddress();
		// Resolve labels in J-TYPE instructions
		ResolveLabels();
	} catch( Error& e ) {
		AfxMessageBox( e.GetStrError() );
		return FALSE;
	}

	strBuf.Empty();
	return TRUE;
}

BOOL CMIPSSimulator::Trace( LPCTSTR pathname )
{
	// close the file if necessary
	if( m_TraceFile.m_hFile != CFile::hFileNull )
		m_TraceFile.Close();
	// create the output file
	CFileException e;
	if( !m_TraceFile.Open( pathname, CFile::modeCreate |
		CFile::modeWrite, &e ) ) {
		CString temp;
		temp.Format( "failed to open %s\n%s", pathname, e.m_cause );
		AfxMessageBox( temp );
		return FALSE;
	}
	m_bTrace = TRUE;
	return TRUE;
}

void CMIPSSimulator::StopTrace()
{
	if( m_TraceFile.m_hFile != CFile::hFileNull )
		m_TraceFile.Close();
}

/////////////////////////////////////////////////////////
// Asign memory addresses and Resolve labels
void CMIPSSimulator::AsignAddress()
{
	UINT address = m_nDataSize;
	POSITION pos = m_pInsts->m_instList.GetHeadPosition();
	while( pos ) {
		CAsmInstruction* pInst = m_pInsts->m_instList.GetNext( pos );
		pInst->m_nAddress = address;
		address += 4;
	}
}

int CMIPSSimulator::FindTargetAddress( CString& target )
{
	POSITION pos = m_pInsts->m_instList.GetHeadPosition();
	while( pos ) {
		CAsmInstruction* pInst = m_pInsts->m_instList.GetNext( pos );
		if( pInst->m_strLabel == target )
			return pInst->m_nAddress;
	}
	return -1;
}

void CMIPSSimulator::ResolveLabels()
{
	POSITION pos = m_pInsts->m_instList.GetHeadPosition();
	while( pos ) {
		CAsmInstruction* pInst = m_pInsts->m_instList.GetNext( pos );
		if( pInst->m_key == J || pInst->m_key == BEQZ || pInst->m_key == BNEZ ) {
			int address = FindTargetAddress( pInst->m_inst.target );
			if( address < 0 )
				throw Error( ERROR_ASM_TARGET, 0, pInst->m_inst.target );
			if( pInst->m_key == J )
				pInst->m_inst.inst.j.offset = address>>2;
			else {
				int offset = address - pInst->m_nAddress - 4;
				pInst->m_inst.inst.i.imm = offset;
			}
		}
	}
}

int CMIPSSimulator::FindIndexFromAddress( UINT address )
{
	int index = 0;
	POSITION pos = m_pInsts->m_instList.GetHeadPosition();
	while( pos ) {
		CAsmInstruction* pInst;
		pInst = m_pInsts->m_instList.GetNext( pos );
		if( pInst->m_nAddress == address )
			return index;
		index++;
	}
	return -1;
}

//

/////////////////////////////////////////////////////////
// Clear MIPS CPU Registers
void CMIPSSimulator::ClearIFIDReg()
{
	IFID.NPC = 0;
	IFID.IR = NULL;
}

void CMIPSSimulator::ClearIDEXReg()
{
	IDEX.A = 0;
	IDEX.B = 0;
	IDEX.Imm = 0;
	IDEX.IR = NULL;
}

void CMIPSSimulator::ClearEXMEMReg()
{
	EXMEM.ALUOutput = 0;
	EXMEM.B = 0;
	EXMEM.IR = NULL;
}

void CMIPSSimulator::ClearMUL_EXMEMReg()
{
	MUL_EXMEM.ALUOutput = 0;
	MUL_EXMEM.B = 0;
	MUL_EXMEM.IR = NULL;
}

void CMIPSSimulator::ClearDIV_EXMEMReg()
{
	DIV_EXMEM.ALUOutput = 0;
	DIV_EXMEM.B = 0;
	DIV_EXMEM.IR = NULL;
}

void CMIPSSimulator::ClearMEMWBReg()
{
	MEMWB.ALUOutput = 0;
	MEMWB.LMD = 0;
	MEMWB.IR = NULL;
}

void CMIPSSimulator::ClearMUL_MEMWBReg()
{
	MUL_MEMWB.ALUOutput = 0;
	MUL_MEMWB.LMD = 0;
	MUL_MEMWB.IR = NULL;
}

void CMIPSSimulator::ClearDIV_MEMWBReg()
{
	DIV_MEMWB.ALUOutput = 0;
	DIV_MEMWB.LMD = 0;
	DIV_MEMWB.IR = NULL;
}
//

// Set Program Counter
BOOL CMIPSSimulator::SetPC(UINT address)
{
	POSITION pos = m_pInsts->m_instList.GetHeadPosition();
	while( pos ) {
		CAsmInstruction* pInst = m_pInsts->m_instList.GetNext( pos );
		if( pInst->m_nAddress == address ) {
			PC = address;
			return TRUE;
		}
	}
	return FALSE;
}

// fetch instruction pointed by PC;
CAsmInstruction* CMIPSSimulator::FetchInst()
{
	CAsmInstruction* pInst = NULL;
	POSITION pos = m_pInsts->m_instList.GetHeadPosition();
	while( pos ) {
		pInst = m_pInsts->m_instList.GetNext( pos );
		if( pInst->m_nAddress == PC ) {
			CalcStat( pInst );
			m_bNewStep = TRUE;
			/*
			 * trace instructions
			 */
			if( m_bTrace ) {
				CString temp;
				temp.Format( "STEP:%3d CYCLE:%3d  %s\r\n", GetCurStep(),
					GetCurCycle() + 1, (LPCTSTR)pInst->InstWithLabelAddress() );
				try {
					m_TraceFile.Write( (LPCTSTR)temp, temp.GetLength() );
					m_TraceFile.Flush();
				} catch( CFileException* e ) {
					temp.Format( "%s", e->m_cause );
					AfxMessageBox( temp );
				}
			}

			return pInst;
		}
	}
	return NULL;
}

void CMIPSSimulator::CalcStat(CAsmInstruction* pInst)
{
	STAT.steps++;
	// increase instruction count
	int* p = (int*)&STAT;
	p[(int)pInst->m_key]++;
}

/////////////////////////////////////////////////////////
// Execution

void CMIPSSimulator::Start()
{
	ASSERT( m_pExecInsts->next == NULL );
	ASSERT( data != NULL );

	// trace
	if( m_bTrace ) {
		CString temp = _T("Program start:\r\n");
		m_TraceFile.Write( (LPCTSTR)temp, temp.GetLength() );
		m_TraceFile.Flush();
	}

	m_nState = kRun;
	BackupMem();
	BackupReg();
	m_nStartPC = PC;
	m_pExecInsts->m_nCurCycle = 1;
	m_pExecInsts->FetchInst();
	STAT.cycles = 0;
}

void CMIPSSimulator::NextCycle()
{
	if( m_nState == kComplete ) return;
	if( IsExecComplete() ) m_nState = kComplete;

	m_bNewStep = FALSE;
	m_nLastPC = PC;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -