Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
            }
        }
    }