📄 mipssimulator.cpp
字号:
// 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 + -