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

📄 mipssimulator.cpp

📁 一个牛人做的MIPS模拟器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	if( m_pExecInsts->next )
		m_pExecInsts->next->NextCycle();
	STAT.cycles++;
}

void CMIPSSimulator::PrevCycle()
{
	CycleTo( STAT.cycles - 1 );
}

void CMIPSSimulator::RollBackToStartState()
{
	m_nState = kRun;
	PC = m_nStartPC;
	RollBackMem();
	RollBackReg();
	memset( &STAT, 0, sizeof(STAT) );
	if( m_pExecInsts->next ) {
		delete m_pExecInsts->next; m_pExecInsts->next = NULL;
	}

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

	m_pExecInsts->m_nCurCycle = 1;
	m_pExecInsts->FetchInst();
	STAT.cycles = 0;
}

void CMIPSSimulator::CycleTo( int cycle )
{
	RollBackToStartState();
	while( STAT.cycles < cycle )
		NextCycle();
}

int CMIPSSimulator::GetCurCycle()
{
	return STAT.cycles;
}

int CMIPSSimulator::GetCurStep()
{
	return STAT.steps;
}

// The space pExecInst pointed is deallocated after this function
BOOL CMIPSSimulator::GetStageArray( CExecInst* pExecInst,
	UINT_ARRAY& outStageArray )
{
	BOOL found = FALSE;
	CExecInst* next = m_pExecInsts->next;
	while( next ) {
		if( next == pExecInst ) {
			found = TRUE; break;
		}
		next = next->next;
	}
	if( !found ) {
#ifdef _DEBUG
		AfxMessageBox( "CMIPSSimulator::GetStageArray(..) error." );
#endif //_DEBUG
		return FALSE;// It should not occur.
	}
	// close trace
	BOOL bTrace = m_bTrace; m_bTrace = FALSE;
	UINT nCurCycle = pExecInst->m_nCurCycle;
	outStageArray.Add( pExecInst->m_nLastStage );
	while( pExecInst->m_nCurStage != COMPLETE ) {
		NextCycle();
		outStageArray.Add( pExecInst->m_nLastStage );
	}
	// Roll back
	CycleTo( nCurCycle );
	// 
	m_bTrace = bTrace;
	return TRUE;
}

BOOL CMIPSSimulator::HasNewStep()
{
	return m_bNewStep;
}

CExecInst* CMIPSSimulator::GetNewExecInst()
{
	CExecInst* next = m_pExecInsts->next;
	while( next && next->next ) {
		next = next->next;
	}
	return next;
}

BOOL CMIPSSimulator::HasInstComplete(UINT_ARRAY& outCompleteArray)
{
	outCompleteArray.RemoveAll();
	CExecInst* next = m_pExecInsts->next;
	while( next ) {
		if( next->m_nCurStage == COMPLETE && next->pInst->m_key != IDLE_INST )
			outCompleteArray.Add( next->pInst->m_nAddress );
		next = next->next;
	}
	if( outCompleteArray.GetSize() > 0 ) return TRUE;
	return FALSE;
}

BOOL CMIPSSimulator::HasIdleInstComplete()
{
	CExecInst* next = m_pExecInsts->next;
	while( next ) {
		if( next->m_nCurStage == COMPLETE && next->pInst->m_key == IDLE_INST )
			return TRUE;
		next = next->next;
	}
	return FALSE;
}

BOOL CMIPSSimulator::IsExecComplete()
{
	if( m_pExecInsts->next == NULL )
		return TRUE;
	return FALSE;
}








/////////////////////////////////////////////////////////
// CLASS CEXECINST
/////////////////////////////////////////////////////////
// Construction
CExecInst::CExecInst( int cycle, CAsmInstruction* inst,
					 CExecInst* prev, CExecInst* next )
{
	m_nStartCycle	= cycle;
	m_nCurCycle		= cycle - 1;
	m_nCurMulCycle	= 0;
	m_nCurDivCycle	= 0;
	m_nCurStage		= IF;
	m_nLastStage	= IF;
	m_bBranchTaken	= TRUE;
	m_bStall		= FALSE;
	m_bIdle			= FALSE;

	m_nA			= 0;
	m_nB			= 0;
	m_nImm			= 0;
	
	pInst = inst;
	// link the previous and next node
	this->prev = prev;
	this->next = next;
	if( prev ) prev->next = this;
	if( next ) next->prev = this;

	// prevent data hazards
	m_bForward	= FALSE;
	m_bForwardReady = FALSE;
	m_bReadFromForward = FALSE;
}

CExecInst::~CExecInst()
{
	if( pInst && pInst->m_key == IDLE_INST )// create by Freeze()
		delete pInst;
	if( prev ) prev->next = NULL;
	if( next ) {
		next->prev = NULL;
		delete next;
	}
}

// MIPS CPU: DO ONE CYCLE
void CExecInst::NextCycle()
{
	m_nCurCycle++;

	// for stageComplete() delete itself
	CExecInst* pNextExecInst = next;

	switch( m_nCurStage ) {
	case IF:
		stageIF(); break;
	case ID:
		stageID();
		pNextExecInst = next;// this stage load the next instruction
		break;
	case EX:
		stageEX(); break;
	case MEM:
		stageMEM(); break;
	case WB:
		stageWB(); break;
	case COMPLETE:
		stageComplete();
	}

	// Recursive call
	if( pNextExecInst ) pNextExecInst->NextCycle();
}

// stall call
void CExecInst::Stall()
{
	m_bStall = TRUE;
	if( next ) next->Stall();
}

// idle call, clear next stage registers
void CExecInst::Idle()
{
	m_bIdle = TRUE;
}

// Fetch the next instruction...
COLORREF ColorArray[] = 
{
	RGB(255,0,0), RGB(128,0,0), RGB(0,0,255),
	RGB(0,128,0), RGB(0,0,160), RGB(255,0,255),
	RGB(128,128,0), RGB(0,64,128), RGB(0,128,128),
	RGB(255,128,0)
};

void CExecInst::FetchInst()
{
	CAsmInstruction* pInst = simulator.FetchInst();
	if( pInst ) {
		CExecInst* pExecInst = new CExecInst( m_nCurCycle,
			pInst, this, this->next );
		pExecInst->color = ColorArray[m_nCurCycle % 10];
	}
}

// Freeze the pipeline, deleting any instructions after the branch
void CExecInst::Freeze()
{
	simulator.m_bNewStep = TRUE;

	CAsmInstruction* pInst = CAsmInstruction::IdleInst();
	CExecInst* pExecInst = new CExecInst( m_nCurCycle, pInst, this, this->next );
	pExecInst->Idle();
	pExecInst->color = ColorArray[m_nCurCycle % 10];
}

/////////////////////////////////////////////////////////
// MIPS CPU Registers Access
int CExecInst::GetRegContent(UINT reg)
{
	if( reg < 32 )
		return simulator.reg[reg].content;
	throw Error(ERROR_MIPS_REG_OUTRANGE, reg);
}

int CExecInst::GetRegForward(UINT reg)
{
	if( reg < 32 )
		return simulator.reg[reg].forward;
	throw Error(ERROR_MIPS_REG_OUTRANGE, reg);
}

int CExecInst::GetRegStatus(UINT reg)
{
	if( reg < 32 )
		return simulator.reg[reg].status;
	throw Error(ERROR_MIPS_REG_OUTRANGE, reg);
}

int CExecInst::GetRegData(UINT reg)
{
	if( reg < 32 ) {
		if( m_bReadFromForward ) {
			m_bReadFromForward = FALSE;
			return simulator.reg[reg].forward;
		} else
			return simulator.reg[reg].content;
	}
	throw Error(ERROR_MIPS_REG_OUTRANGE, reg);
}

void CExecInst::SetRegContent(UINT reg, int content)
{
	if( reg < 32 ) {
		if( reg > 0 ) {// R0 is always be 0
			simulator.reg[reg].content = content;
			if( simulator.reg[reg].write_count > 0 )
				simulator.reg[reg].write_count--;
			if( simulator.reg[reg].write_count == 0 )
				simulator.reg[reg].status = kReady;
			else
				simulator.reg[reg].status = kWrite;
		}
	} else
		throw Error(ERROR_MIPS_REG_OUTRANGE, reg);
}

void CExecInst::SetRegForward(UINT reg, int forward)
{
	if( reg < 31 ) {
		// R0 is always be 0
		if( reg > 0 && simulator.m_bForwardingEnable ) {
			simulator.reg[reg].forward = forward;
			m_bForward = TRUE;
		}
	} else
		throw Error(ERROR_MIPS_REG_OUTRANGE, reg);
}

void CExecInst::SetRegStatus(UINT reg, int status)
{
	if( reg < 31 ) {
		if( reg > 0 ) {// R0 is always be 0
			simulator.reg[reg].status = status;
			if( status == kWrite )
				simulator.reg[reg].write_count++;
		}
	} else
		throw Error(ERROR_MIPS_REG_OUTRANGE, reg);
}

int CExecInst::GetImm()
{
	if( pInst->m_inst.type == TYPE_I )
		return (int)pInst->m_inst.inst.i.imm;
	return 0;
}
//

/////////////////////////////////////////////////////////
int CExecInst::ReadMem(UINT address)
{
	if( address < simulator.m_nDataSize )
		return simulator.data[address/4];
	throw Error(ERROR_MIPS_MEM_OUTRANGE, address);
}

void CExecInst::WriteMem(UINT address, int content)
{
	if( address < simulator.m_nDataSize )
		simulator.data[address/4] = content;
	else
		throw Error(ERROR_MIPS_MEM_OUTRANGE, address);
}

/////////////////////////////////////////////////////////
// Stage Operations
// IF
void CExecInst::stageIF()
{
	if( m_bStall ) {
		// stall this cycle, remain in stage IF
		m_nLastStage = STALL;
		m_bStall = FALSE;
	} else if( m_bIdle ) {
		// clear cpu registers and go to next stage
		m_nLastStage = IDLE;
		m_nCurStage = ID;
		simulator.ClearIFIDReg();
	} else {
		// put results into IF/ID registers and
		// go to next stage
		m_nLastStage = IF;
		m_nCurStage = ID;// Go to next cycle
		simulator.PC += 4;
		simulator.IFID.IR = pInst;
		simulator.IFID.NPC = simulator.PC;
	}
}

// ID
void CExecInst::stageID()
{
	if( m_bStall ) {
		// stall this cycle, remain in stage ID
		m_nLastStage = STALL;
		m_bStall = FALSE;
	} else if( m_bIdle ) {
		// Read in the next instruction.
		// clear cpu registers and go to next stage
		FetchInst();
		m_nLastStage = IDLE;
		m_nCurStage = EX;
		simulator.ClearIDEXReg();
	} else {
		// Read in the next instruction, decode
		// Put results into ID/EX registers and go to next stage.
		m_nLastStage = ID;
		m_nCurStage = EX;// Go to next cycle
		switch( pInst->m_inst.type ) {
		case TYPE_R:
			// fetch next instruction
			if( next == NULL ) FetchInst();
			SetRegStatus(pInst->m_inst.inst.r.rd, kWrite);
			simulator.IDEX.A = GetRegContent(pInst->m_inst.inst.r.rs);
			simulator.IDEX.B = GetRegContent(pInst->m_inst.inst.r.rt);
			simulator.IDEX.Imm = 0;
			simulator.IDEX.IR = pInst;
			// If forwarding is disable, check data hazards
			if( !simulator.m_bForwardingEnable &&
				(GetRegStatus(pInst->m_inst.inst.r.rs) == kWrite ||
				GetRegStatus(pInst->m_inst.inst.r.rt) == kWrite) ) {
				m_nLastStage = STALL;
				m_nCurStage = ID;
				if( next ) next->Stall();
				return;
			}
			break;

		case TYPE_I:
			// set register status
			if( pInst->m_key != SW && pInst->m_key != BEQZ &&
				pInst->m_key != BNEZ && pInst->m_key != JR )
				SetRegStatus(pInst->m_inst.inst.i.rt, kWrite);
			simulator.IDEX.A = GetRegContent(pInst->m_inst.inst.i.rs);
			simulator.IDEX.B = GetRegContent(pInst->m_inst.inst.i.rt);
			simulator.IDEX.Imm = GetImm();
			simulator.IDEX.IR = pInst;
			// If forwarding is disable, check data hazards
			if( !simulator.m_bForwardingEnable &&
				(GetRegStatus(pInst->m_inst.inst.r.rs) == kWrite ||
				(pInst->m_key == SW)?(GetRegStatus(pInst->m_inst.inst.r.rt) == kWrite):FALSE) ) {
				m_nLastStage = STALL;
				m_nCurStage = ID;
				if( next ) next->Stall();
				return;
			}
			// For BEQZ and BNEZ, use different Branch strategies
			if( pInst->m_key == BEQZ || pInst->m_key == BNEZ || pInst->m_key == JR ) {
				// Methods
				if( simulator.m_nBranchMethod == CMIPSSimulator::kFreeze ||
					simulator.m_nBranchMethod == CMIPSSimulator::kPredictedTaken ) {
					// Freeze and Branch-Taken methods, 
					// they are the same in 5-stage integer pipeline
					// read in the next instruction, NOP
					if( !next )	Freeze();
				} else {
					// Predicted-Not-Taken and Delayed slot,
					// fetch the next instruction
					// read in the next instruction, NORMAL
					if( !next ) FetchInst();
				}
				if( HasDataHazards(pInst->m_inst.inst.i.rs) ) {
					// Data hazzard, stall
					m_nLastStage = STALL;
					m_nCurStage = ID;
					if( next ) next->Stall();
					return;
				}
				// for conditional branch BEQZ and BNEZ

⌨️ 快捷键说明

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