UINT getNextPCAddress(MipsSimContext *pContext, UINT InstAddress) { BTBEntry *branchDetails = checkInstructionInBTB(pContext, InstAddress); UINT NextPCAddress = InstAddress; Instruction *pInst = getInstFromList(pContext, InstAddress); BTBEntry *pBTBEntry = NULL; if (branchDetails != NULL) { // Branch entry found in BTB!! branchDetails->HitRate++; if (branchDetails->PredState == BRANCH_TAKEN) { // Pred State is Taken NextPCAddress = branchDetails->TargetAddress; pInst->BranchPred = BRANCH_TAKEN; } else { // Either the Pred State is Not Taken or is not set // Move to the next PC NextPCAddress += 4; pInst->BranchPred = BRANCH_NOT_TAKEN; } } else { // Add a new entry in the BTB! // if Branch or Jum Instruction, add an entry in BTB if not present if (pInst->IsJumpInst || pInst->IsBranchInst) { if (checkInstructionInBTB(pContext, pInst->InstAddress) == NULL) { // Add entry in BTB pBTBEntry = (BTBEntry*)malloc(sizeof(BTBEntry)); pBTBEntry->InstAddress = pInst->InstAddress; if (pInst->IsJumpInst) { pBTBEntry->TargetAddress = pInst->InstructionDWord.JType.Target * 4; } else { pBTBEntry->TargetAddress = pInst->InstAddress + 4 + pInst->InstructionDWord.IType.SignedImmediate * 4; } pBTBEntry->PredState = NOT_SET; pBTBEntry->HitRate = 1; pBTBEntry->next = NULL; insertNewPredAtISStage(pContext, pBTBEntry); pInst->BranchPred = BRANCH_NOT_TAKEN; } } NextPCAddress += 4; } return NextPCAddress; }
void updatePredAtEXStage(MipsSimContext *pContext, UINT InstAddress, UINT PredState) { BTBEntry *pBTBEntry = NULL; // Get the Instruction from the BTB table pBTBEntry = checkInstructionInBTB(pContext, InstAddress); pBTBEntry->PredState = PredState; }
void executeInst(MipsSimContext *pContext) { UINT CurrRSEntry = 0; Instruction *pInst = NULL; UINT count = 0; bool ComputeAddress = true; UINT ROBCount = 0; UINT RSCount = 0; // Check if there is an instruction ready in RS to execute for (CurrRSEntry = 0; CurrRSEntry < MAX_RS_ENTRIES; CurrRSEntry++) { if (pContext->RS[CurrRSEntry].Busy && pContext->RS[CurrRSEntry].pInst->PipelineStage == INSTRUCTION_EX) { pInst = pContext->RS[CurrRSEntry].pInst; // To check whehter the instruction can start execution // NOP and BREAK Instructions will not enter this stage // For Jump Instruction start execution, operand will be available // if both Rs & Rt were operands and both are available, then start // if Rs is the only operand, then check for only Qj // if Rt is the only operand, then check for only Qk if ((pInst->IsRsUsedAsOperand && pInst->IsRtUsedAsOperand && pContext->RS[CurrRSEntry].Qj == MAX_ROB_ENTRIES && pContext->RS[CurrRSEntry].Qk == MAX_ROB_ENTRIES) || (pInst->IsRsUsedAsOperand && !pInst->IsRtUsedAsOperand && pContext->RS[CurrRSEntry].Qj == MAX_ROB_ENTRIES) || (!pInst->IsRsUsedAsOperand && pInst->IsRtUsedAsOperand && pContext->RS[CurrRSEntry].Qk == MAX_ROB_ENTRIES) || pInst->IsJumpInst) { // Operands availble, EXECUTE !!!!! switch (pInst->Opcode) { case OPCODE_SPECIAL: switch (pInst->InstructionDWord.RType.Function) { case FUNC_SRL: case FUNC_SRA: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj >> pContext->RS[CurrRSEntry].Vk; break; case FUNC_SLL: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj << pContext->RS[CurrRSEntry].Vk; break; case FUNC_ADD: case FUNC_ADDU: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj + pContext->RS[CurrRSEntry].Vk; break; case FUNC_SUB: case FUNC_SUBU: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj - pContext->RS[CurrRSEntry].Vk; break; case FUNC_AND: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj & pContext->RS[CurrRSEntry].Vk; break; case FUNC_OR: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj | pContext->RS[CurrRSEntry].Vk; break; case FUNC_XOR: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj ^ pContext->RS[CurrRSEntry].Vk; break; case FUNC_NOR: pContext->RS[CurrRSEntry].Result = ~(pContext->RS[CurrRSEntry].Vj | pContext->RS[CurrRSEntry].Vk); break; case FUNC_SLT: case FUNC_SLTU: pContext->RS[CurrRSEntry].Result = (pContext->RS[CurrRSEntry].Vj < pContext->RS[CurrRSEntry].Vk) ? 1 : 0; break; default: // should not reach here! break; } break; case OPCODE_REGIMM: switch (pInst->InstructionDWord.IType.Rt) { case RT_BLTZ: if (pContext->RS[CurrRSEntry].Vj < 0) { // Branch Taken pInst->BranchOutcome = BRANCH_TAKEN; } else { // Branch Not Taken pInst->BranchOutcome = BRANCH_NOT_TAKEN; } // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; break; case RT_BGEZ: if (pContext->RS[CurrRSEntry].Vj >= 0) { // Branch Taken pInst->BranchOutcome = BRANCH_TAKEN; } else { // Branch Not Taken pInst->BranchOutcome = BRANCH_NOT_TAKEN; } // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; break; default: // shoudld not reach here! break; } case OPCODE_J: // Branch Taken pInst->BranchOutcome = BRANCH_TAKEN; // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; break; case OPCODE_BEQ: if (pContext->RS[CurrRSEntry].Vj == pContext->RS[CurrRSEntry].Vk) { // Branch Taken pInst->BranchOutcome = BRANCH_TAKEN; } else { // Branch Not Taken pInst->BranchOutcome = BRANCH_NOT_TAKEN; } // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; break; case OPCODE_BNE: if (pContext->RS[CurrRSEntry].Vj != pContext->RS[CurrRSEntry].Vk) { // Branch Taken pInst->BranchOutcome = BRANCH_TAKEN; } else { // Branch Not Taken pInst->BranchOutcome = BRANCH_NOT_TAKEN; } // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; break; case OPCODE_BLEZ: if (pContext->RS[CurrRSEntry].Vj <= 0) { // Branch Taken pInst->BranchOutcome = BRANCH_TAKEN; } else { // Branch Not Taken pInst->BranchOutcome = BRANCH_NOT_TAKEN; } // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; break; case OPCODE_BGTZ: if (pContext->RS[CurrRSEntry].Vj > 0) { // Branch Taken pInst->BranchOutcome = BRANCH_TAKEN; } else { // Branch Not Taken pInst->BranchOutcome = BRANCH_NOT_TAKEN; } // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; break; case OPCODE_ADDI: case OPCODE_ADDIU: pContext->RS[CurrRSEntry].Result = pContext->RS[CurrRSEntry].Vj + pContext->RS[CurrRSEntry].Vk; break; case OPCODE_SLTI: pContext->RS[CurrRSEntry].Result = (pContext->RS[CurrRSEntry].Vj < pContext->RS[CurrRSEntry].Vk) ? 1 : 0; break; case OPCODE_LW: // For Address Generation, all Load/Stores ahead of this store should have their address generated! // Go through current ROB entries and make this check for (count = 0; count < MAX_ROB_ENTRIES; count++) { if (pContext->ROB[count].Busy && pContext->ROB[count].pInst != pInst && pContext->ROB[count].pInst->IsLoadOrStoreInst && pContext->ROB[count].pInst->InstIssueNum < pInst->InstIssueNum && !pContext->ROB[count].pInst->IsLoadOrStoreAddrComputed) { ComputeAddress = false; break; } } if (ComputeAddress) { // Proceed with Address Computation for Load pContext->RS[CurrRSEntry].Addr = pContext->RS[CurrRSEntry].Vj + pContext->RS[CurrRSEntry].Addr; pInst->IsLoadOrStoreAddrComputed = true; } break; case OPCODE_SW: // For Address Generation, all Load/Stores ahead of this store should have their address generated! // Go through current ROB entries and make this check for (count = 0; count < MAX_ROB_ENTRIES; count++) { if (pContext->ROB[count].Busy && pContext->ROB[count].pInst->InstAddress != pInst->InstAddress && pContext->ROB[count].pInst->IsLoadOrStoreInst && pContext->ROB[count].pInst->InstIssueNum < pInst->InstIssueNum && !pContext->ROB[count].pInst->IsLoadOrStoreAddrComputed) { ComputeAddress = false; break; } } if (ComputeAddress) { // Proceed with Address Computation for Store pContext->RS[CurrRSEntry].Addr = pContext->RS[CurrRSEntry].Vj + pContext->RS[CurrRSEntry].Addr; pInst->IsLoadOrStoreAddrComputed = true; } // Update the value in ROB pContext->ROB[pContext->RS[CurrRSEntry].Dest].Value = pContext->RS[CurrRSEntry].Vk; // Mark the instruction to be ready pContext->ROB[pContext->RS[CurrRSEntry].Dest].Ready = true; // Write the result of the Address to the ROB pContext->ROB[pContext->RS[CurrRSEntry].Dest].Addr = pContext->RS[CurrRSEntry].Addr; break; default: // should not reach here! break; } // Update PC here itself if (pInst->IsBranchInst || pInst->IsJumpInst) { if (pInst->BranchOutcome == BRANCH_NOT_TAKEN && pInst->BranchPred == BRANCH_TAKEN) { // Update PC to PC + 4 pContext->CurrentPC = pInst->InstAddress + 4; // Cancel all Instructions fetched after Branch in ROB for (ROBCount = 0; ROBCount < MAX_ROB_ENTRIES; ROBCount++) { if (pContext->ROB[ROBCount].pInst->InstIssueNum > pInst->InstIssueNum) { // Free up ROB and RS pContext->ROB[ROBCount].UpdateBusyStatus = true; for (RSCount = 0; RSCount < MAX_RS_ENTRIES; RSCount++) { if (pContext->RS[RSCount].Dest == ROBCount) { pContext->RS[RSCount].UpdateBusyStatus = true; break; } } } } // Also remove the last instruction from Instruction Queue pContext->RemoveInstFromQueue = true; } if (pInst->BranchOutcome == BRANCH_TAKEN && (pInst->BranchPred == BRANCH_NOT_TAKEN || pInst->BranchPred == NOT_SET)) { // Update PC to new Target pContext->CurrentPC = checkInstructionInBTB(pContext, pInst->InstAddress)->TargetAddress; // Cancel all Instructions fetched after Branch in ROB for (ROBCount = 0; ROBCount < MAX_ROB_ENTRIES; ROBCount++) { if (pContext->ROB[ROBCount].pInst->InstIssueNum > pInst->InstIssueNum) { // Free up ROB and RS pContext->ROB[ROBCount].UpdateBusyStatus = true; for (RSCount = 0; RSCount < MAX_RS_ENTRIES; RSCount++) { if (pContext->RS[RSCount].Dest == ROBCount) { pContext->RS[RSCount].UpdateBusyStatus = true; break; } } } } // Also remove the last instruction from Instruction Queue pContext->RemoveInstFromQueue = true; } } if (pInst->IsBranchInst || pInst->IsJumpInst) { pInst->UpdatePred = true; } // Move to the next stage in next cycle pContext->RS[CurrRSEntry].pInst->UpdatePipelineStage = true; } } }