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

📄 mipssimulator.cpp

📁 一个牛人做的MIPS模拟器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				// check if taken, and updata PC
				if( pInst->m_key == BEQZ ) {
					if( GetRegData(pInst->m_inst.inst.i.rs) == 0 ) {
						m_bBranchTaken = TRUE;
						simulator.PC = simulator.IFID.NPC + simulator.IDEX.Imm;
						if( simulator.m_nBranchMethod == CMIPSSimulator::kPredictedNotTaken ||
							simulator.m_nBranchMethod == CMIPSSimulator::kDelayedBranch )
							simulator.PC -= 4;
					}
				} else if( pInst->m_key == BNEZ ) {
					if( GetRegData(pInst->m_inst.inst.i.rs) != 0 ) {
						m_bBranchTaken = TRUE;
						simulator.PC = simulator.IFID.NPC + simulator.IDEX.Imm;
						if( simulator.m_nBranchMethod == CMIPSSimulator::kPredictedNotTaken ||
							simulator.m_nBranchMethod == CMIPSSimulator::kDelayedBranch )
							simulator.PC -= 4;
					}
				} else {
					// JR
					simulator.PC = GetRegData( pInst->m_inst.inst.i.rs );
				}
			} else
				// fetch next instruction
				if( !next ) FetchInst();
			break;

		case TYPE_J:
			if( pInst->m_key == TRAP ) 
				// program completes
				// just RETURN, do NOT fetch any instruction following
				return;
			else if( pInst->m_key == J ) {
				// j name
				simulator.IDEX.A = 0;
				simulator.IDEX.B = 0;
				simulator.IDEX.Imm = 0;
				simulator.IDEX.IR = pInst;
				// 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
					Freeze();
				} else {
					// Predicted-Not-Taken and Delayed slot,
					// fetch the next instruction
					FetchInst();
				}
				// update PC
				simulator.PC &= 0xF0000000;
				simulator.PC += pInst->m_inst.inst.j.offset<<2;
			}
			break;
		}
	}
}

// EX
void CExecInst::stageEX()
{
	if( pInst->m_key == MUL || pInst->m_key == MULI ||
		pInst->m_key == MUT || pInst->m_key == MUTI ||
		pInst->m_key == DIV || pInst->m_key == DIVI )
		// DON'T STALL
		m_bStall = FALSE;

	if( m_bStall ) {
		// stall this cycle, remain in stage EX
		m_nLastStage = STALL;
		m_bStall = FALSE;
	} else if( m_bIdle ) {
		m_nLastStage = IDLE;
		m_nCurStage = MEM;
		simulator.ClearEXMEMReg();
	} else {
		m_nLastStage = EX;
		m_nCurStage = MEM;// Go to next cycle
		simulator.EXMEM.B = simulator.IDEX.B;
		simulator.EXMEM.IR = pInst;
		switch( pInst->m_inst.type ) {
		case TYPE_R:
			if( m_nCurMulCycle == 0 && m_nCurDivCycle == 0 ) {
				if( HasDataHazards(pInst->m_inst.inst.r.rs) ) {
					// Data hazard, stall
					m_nLastStage = STALL;
					m_nCurStage = EX;
					if( next ) next->Stall();
					return;
				} else
					m_nA = GetRegData(pInst->m_inst.inst.r.rs);
				if(	HasDataHazards(pInst->m_inst.inst.r.rt) ) {
					// Data hazard, stall
					m_nLastStage = STALL;
					m_nCurStage = EX;
					if( next ) next->Stall();
					return;
				} else
					m_nB = GetRegData(pInst->m_inst.inst.r.rt);
			}
			switch( pInst->m_key ) {
			case IDLE_INST:
			case ADD:
				simulator.EXMEM.ALUOutput = m_nA + m_nB;
				SetRegForward(pInst->m_inst.inst.r.rd, simulator.EXMEM.ALUOutput);
				break;

			case SUB:
				simulator.EXMEM.ALUOutput = m_nA - m_nB;
				SetRegForward(pInst->m_inst.inst.r.rd, simulator.EXMEM.ALUOutput);
				break;

			case MUL:
			case MUT:
				m_nCurMulCycle++;
				if( (UINT)m_nCurMulCycle < simulator.m_nMulDelay ) {
					// go to next EX cycle
					m_nLastStage = EX;
					m_nCurStage = EX;
				} else {
					simulator.MUL_EXMEM.ALUOutput = m_nA * m_nB;
					simulator.MUL_EXMEM.IR = pInst;
					SetRegForward(pInst->m_inst.inst.r.rd, simulator.MUL_EXMEM.ALUOutput);
				}
				break;

			case DIV:
				if( !m_nCurDivCycle ) {
					// begin DIV cycle
					// DIV line is not piped
					if( HasStructualHazards() ) {
						// structual hazards, stall
						m_nLastStage = STALL;
						m_nCurStage = EX;
						if( next ) next->Stall();
						return;
					}
				}
				m_nCurDivCycle++;
				if( (UINT)m_nCurDivCycle < simulator.m_nDivDelay ) {
					// go to next EX cycle
					m_nLastStage = EX;
					m_nCurStage = EX;
				} else {
					simulator.DIV_EXMEM.ALUOutput = m_nA / m_nB;
					simulator.DIV_EXMEM.IR = pInst;
					SetRegForward(pInst->m_inst.inst.r.rd, simulator.DIV_EXMEM.ALUOutput);
				}
				break;

			case AND:
				simulator.EXMEM.ALUOutput = m_nA & m_nB;
				SetRegForward(pInst->m_inst.inst.r.rd, simulator.EXMEM.ALUOutput);
				break;

			case OR:
				simulator.EXMEM.ALUOutput = m_nA | m_nB;
				SetRegForward(pInst->m_inst.inst.r.rd, simulator.EXMEM.ALUOutput);
				break;

			case XOR:
				simulator.EXMEM.ALUOutput = m_nA ^ m_nB;
				SetRegForward(pInst->m_inst.inst.r.rd, simulator.EXMEM.ALUOutput);
				break;
			}
			break;// TYPE_R

		case TYPE_I:
			if( m_nCurMulCycle == 0 && m_nCurDivCycle == 0 ) {
				if( HasDataHazards(pInst->m_inst.inst.i.rs) ) {
					// Data hazard, stall
					m_nLastStage = STALL;
					m_nCurStage = EX;
					if( next ) next->Stall();
					return;
				}
				m_nA = GetRegData(pInst->m_inst.inst.r.rs);
				m_nImm = GetImm();
			}
			switch( pInst->m_key ) {
			case LW:
			case SW:
				simulator.EXMEM.ALUOutput = m_nA + m_nImm;
				break;

			case ADDI:
				simulator.EXMEM.ALUOutput = m_nA + m_nImm;
				SetRegForward(pInst->m_inst.inst.r.rt, simulator.EXMEM.ALUOutput);
				break;

			case SUBI:
				simulator.EXMEM.ALUOutput = m_nA - m_nImm;
				SetRegForward(pInst->m_inst.inst.r.rt, simulator.EXMEM.ALUOutput);
				break;

			case MULI:
			case MUTI:
				m_nCurMulCycle++;
				if( (UINT)m_nCurMulCycle < simulator.m_nMulDelay ) {
					// go to next EX cycle
					m_nLastStage = EX;
					m_nCurStage = EX;
				} else {
					simulator.MUL_EXMEM.ALUOutput = m_nA * m_nImm;
					simulator.MUL_EXMEM.IR = pInst;
					SetRegForward(pInst->m_inst.inst.r.rd, simulator.MUL_EXMEM.ALUOutput);
				}
				break;

			case DIVI:
				if( !m_nCurDivCycle ) {
					// begin DIVI cycle
					// DIV line is not piped
					if( HasStructualHazards() ) {
						// structual hazards, stall
						m_nLastStage = STALL;
						m_nCurStage = EX;
						if( next ) next->Stall();
						return;
					}
				}
				m_nCurDivCycle++;
				if( (UINT)m_nCurDivCycle < simulator.m_nDivDelay ) {
					// go to next EX cycle
					m_nLastStage = EX;
					m_nCurStage = EX;
				} else {
					simulator.DIV_EXMEM.ALUOutput = m_nA / m_nImm;
					simulator.DIV_EXMEM.IR = pInst;
					SetRegForward(pInst->m_inst.inst.r.rd, simulator.DIV_EXMEM.ALUOutput);
				}
				break;

			case ANDI:
				simulator.EXMEM.ALUOutput = m_nA & m_nImm;
				SetRegForward(pInst->m_inst.inst.r.rt, simulator.EXMEM.ALUOutput);
				break;

			case ORI:
				simulator.EXMEM.ALUOutput = m_nA | m_nImm;
				SetRegForward(pInst->m_inst.inst.r.rt, simulator.EXMEM.ALUOutput);
				break;

			case XORI:
				simulator.EXMEM.ALUOutput = m_nA ^ m_nImm;
				SetRegForward(pInst->m_inst.inst.r.rt, simulator.EXMEM.ALUOutput);
				break;

			case BEQZ:
			case BNEZ:
				// For conditional branch BEQZ and BNEZ,
				// if we use Predicted-Not-Taken and result is taken,
				// make the following instruction IDLE
				if( simulator.m_nBranchMethod == CMIPSSimulator::kPredictedNotTaken &&
					m_bBranchTaken == TRUE )
					if( next ) next->Idle();
				break;

			case JR:
				// For unconditional branch JR,
				// if we use Predicted-Not-Taken,
				// make the following instruction IDLE
				if( simulator.m_nBranchMethod == CMIPSSimulator::kPredictedNotTaken )
					if( next ) next->Idle();
				break;
			// default: // do nothing
			}
			break;// TYPE_I

		case TYPE_J:
			if( pInst->m_key == TRAP )
				return;
			else if( pInst->m_key == J ) {
				// For unconditional branch J,
				// if we use Predicted-Not-Taken,
				// make the following instruction IDLE
				if( simulator.m_nBranchMethod == CMIPSSimulator::kPredictedNotTaken )
					if( next ) next->Idle();
				break;
			}
			break;// TYPE_J
		}
	}
}

// MEM
void CExecInst::stageMEM()
{
	if( m_bForward ) m_bForwardReady = TRUE;
	if( m_bStall ) {
		// stall this cycle, remain in stage MEM
		m_nLastStage = STALL;
		m_bStall = FALSE;
	} else if( m_bIdle ) {
		// clear cpu registers and go to next stage
		m_nLastStage = IDLE;
		m_nCurStage = WB;
		simulator.ClearMEMWBReg();
	} else {
		// put results into MEM/WB registers and
		// go to next stage
		m_nLastStage = MEM;
		m_nCurStage = WB;// Go to next cycle
		simulator.MEMWB.ALUOutput = simulator.EXMEM.ALUOutput;
		simulator.MEMWB.IR = pInst;
		simulator.MUL_MEMWB.ALUOutput = simulator.MUL_EXMEM.ALUOutput;
		simulator.MUL_MEMWB.IR = pInst;
		simulator.DIV_MEMWB.ALUOutput = simulator.DIV_EXMEM.ALUOutput;
		simulator.DIV_MEMWB.IR = pInst;
		if( pInst->m_key == LW ) {
			simulator.MEMWB.LMD = ReadMem(simulator.EXMEM.ALUOutput);
			SetRegForward(pInst->m_inst.inst.i.rt, simulator.MEMWB.LMD);
		} else if( pInst->m_key == SW ) {
			if( HasDataHazards(pInst->m_inst.inst.i.rt) ) {
				// This is actually RAW hazards
				m_nLastStage = STALL;
				m_nCurStage = MEM;
				if( next ) next->Stall();
				return;
			}
			// write memory
			WriteMem(simulator.EXMEM.ALUOutput,
				GetRegData(pInst->m_inst.inst.i.rt) );
		}
	}
}

void CExecInst::stageWB()
{
	if( m_bForward ) m_bForwardReady = TRUE;
	if( m_bStall ) {
		// stall this cycle, remain in stage WB
		m_nLastStage = STALL;
		m_bStall = FALSE;
	} else if( m_bIdle ) {
		// complete
		m_nLastStage = IDLE;
		m_nCurStage = COMPLETE;
	} else {
		// check if WAW hazards occur
		if( HasWAWHazards() ) {
			m_nLastStage = STALL;
			if( next ) next->Stall();
			return;
		}
		// put results into MEM/WB registers and
		// go to next stage
		m_nLastStage = WB;
		m_nCurStage = COMPLETE;// Go to next cycle
		switch( pInst->m_inst.type ) {
		case TYPE_R:
			if( pInst->m_key == MUL || pInst->m_key == MUT )
				SetRegContent(pInst->m_inst.inst.r.rd, simulator.MUL_MEMWB.ALUOutput);
			else if( pInst->m_key == DIV )
				SetRegContent(pInst->m_inst.inst.r.rd, simulator.DIV_MEMWB.ALUOutput);
			else
				SetRegContent(pInst->m_inst.inst.r.rd, simulator.MEMWB.ALUOutput);
			break;

		case TYPE_I:
			switch( pInst->m_key ) {
			case MULI:
			case MUTI:
				SetRegContent(pInst->m_inst.inst.i.rt, simulator.MUL_MEMWB.ALUOutput);
				break;
			case DIVI:
				SetRegContent(pInst->m_inst.inst.i.rt, simulator.DIV_MEMWB.ALUOutput);
				break;
			case ADDI:
			case SUBI:
			case ANDI:
			case ORI:
			case XORI:
				SetRegContent(pInst->m_inst.inst.i.rt, simulator.MEMWB.ALUOutput);
				break;
			case LW:
				SetRegContent(pInst->m_inst.inst.i.rt, simulator.MEMWB.LMD);
			}
			break;

		case TYPE_J:
			if( pInst->m_key == TRAP )
				//simulator.m_nState = CMIPSSimulator::kComplete;
				return;
			break;
		}
	}
}

// When this instruction execution complete...
void CExecInst::stageComplete()
{
	if( prev ) prev->next = next;
	if( next ) next->prev = prev;
	prev = next = NULL;
	// destroy itself
	delete this;
}

// check if it has structual hazards
// DIV line are not piped
BOOL CExecInst::HasStructualHazards()
{
	CExecInst* p = this->prev;
	while( p ) {
		if( (pInst->m_key == DIV || pInst->m_key == DIVI) &&
			(p->pInst) &&
			(p->pInst->m_key == DIV || p->pInst->m_key == DIVI) )
			// DIV or DIVI line has been hold
			return TRUE;
		p = p->prev;
	}
	return FALSE;
}

// check if it has data hazards
// if not, must be followed by GetRegData()
BOOL CExecInst::HasDataHazards(int src)
{
	m_bReadFromForward = FALSE;// reset
	if( simulator.reg[src].status == kWrite ) {
		CExecInst* p = this->prev;
		while( p ) {
			if( p->pInst && p->pInst->m_dest == src ) {
				if( p->m_bForwardReady ) {
					// forwarding
					m_bReadFromForward = TRUE;
					break;
				} else
					// has data hazards
					return TRUE;
			}
			p = p->prev;
		}
	}
	return FALSE;
}

// WAW Hazards, Write simutaneously
// stall in WB stage
BOOL CExecInst::HasWAWHazards()
{
	if( pInst->m_dest > 0 ) {
		CExecInst* p = this->prev;
		while( p ) {
			if( (p->pInst) &&
				(p->pInst->m_dest > 0 /*will write back*/) &&
				(p->m_nLastStage == WB) )
				return TRUE;
			p = p->prev;
		}
	}
	return FALSE;
}

⌨️ 快捷键说明

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