예제 #1
0
        /// <summary>
        /// Adds an entry to the rrfTable
        /// </summary>
        /// <param name="instr">Instruction to be added to the rrfTable</param>
        /// <returns>The index (tag) of where it was added</returns>
        public int addEntry(Instruction instr)
        {
            int rrfTag = -1;
            // We had to create one here because we use emptySlot below
            RRFEntry emptySlot = new RRFEntry();

            // Note we're guaranteed an entry is open because we called spaceAvailable
            // at a higher level
            for (int i = 0; i < Config.numRenamingTableEntries; i++)
            {
                if (this.rrfTable[i].busy == false)
                {
                    emptySlot = rrfTable[i];
                    rrfTag = i;
                    break;
                }
            }

            emptySlot.busy = true;
            emptySlot.valid = false;
            // There must be a destination if this instruction requires an RRF entry
            emptySlot.destReg = instr.dest;
            // Data stays null until it's updated by an execution result

            return rrfTag;
        }
예제 #2
0
        /// <summary>
        /// Constructor using initializers
        /// </summary>
        public ReservationStationEntry(int op1, bool valid1, int op2, bool valid2, int robTag, Instruction instr)
        {
            this.op1 = op1;
            this.valid1 = valid1;
            this.op2 = op2;
            this.valid2 = valid2;
            this.robTag = robTag;
            this.instr = instr;

            this.ready = (this.valid1 && this.valid2);

            this.busy = true;
        }
예제 #3
0
 /// <summary>
 /// Add an entry to the reorder buffer
 /// </summary>
 /// <param name="instr">the instruction you need to add an entry for</param>
 public void addEntry(Instruction instr)
 {
     if (Config.numReorderBufferEntries - this.buffer.Count > 0)
     {
         RobEntry newEntry = new RobEntry();
         newEntry.busy = true;
         newEntry.finished = false;
         newEntry.instruction = instr;
         newEntry.valid = this.isNewEntryValid();
         newEntry.renameReg = CPU.rrf.findFirstEmptySlot();
         this.buffer.Enqueue(newEntry);
     }
 }
예제 #4
0
 /// <summary>
 /// Adds and instruction to the dispatch buffer
 /// </summary>
 /// <param name="instr"></param>
 /// <returns></returns>
 private bool addInstructionToBuffer(Instruction instr)
 {
     if (Config.superScalerFactor - this.dispatchBuffer.Count() > 0)
     {
         this.dispatchBuffer.Enqueue(instr);
         return true;
     }
     else
     {
         System.Console.WriteLine("ERROR Tried to add instruction to dispatch buffer when it was full!");
         return false;
     }
 }
예제 #5
0
        /// <summary>
        /// Puts the instruction into the reservation station, filling the entries
        /// Note this does not check if ResStation is full, as that check is done at a higher level
        /// </summary>
        public void ReceiveInstruction(Instruction instr, int robTag)
        {
            // The reservation station entry we're creating
            ReservationStationEntry thisEntry;

            // The fields in the entry
            int op1 = 0, op2 = 0;
            bool valid1 = false, valid2 = false;

            SetUpOp(ref op1, ref valid1, instr.source1, instr.source1Imm);
            SetUpOp(ref op2, ref valid2, instr.source2, instr.source2Imm);

            thisEntry = new ReservationStationEntry(op1, valid1, op2, valid2, robTag, instr);

            this.buffer.Add(thisEntry);
        }
예제 #6
0
        /// <summary>
        /// Puts the instruction into the rename register file
        /// </summary>
        private void dispatchToRenameRegisterFile(Instruction instr)
        {
            if (instr.dest != -1)
            {
                int rrfTag;

                // Add entry to Rename Register File
                rrfTag = CPU.rrf.addEntry(instr);

                // Update the ARF entry of the destination to busy and its tag to point to the RRF entry
                CPU.arf.regFile[instr.dest].busy = true;
                if (rrfTag == -1)
                {
                    Console.WriteLine("-1 rrf tag!");
                }
                CPU.arf.regFile[instr.dest].tag = rrfTag;
            }
        }
예제 #7
0
 /// <summary>
 /// Determines the Instruction type and checks the appropriate Reservation Station for space
 /// </summary>
 /// <param name="instr">The Instrucion that needs moved</param>
 /// <param name="issueStage">The Issue Stage that will handle the instruction</param>
 /// <returns>True if there is space available, false otherwise</returns>
 private bool isReservationStationAvaialble(Instruction instr)
 {
     switch (instr.executionType)
     {
         case Instruction.ExecutionType.Logical:
         case Instruction.ExecutionType.Integer:
             if (CPU.issueStage.integerStation.isFull()) return false;
             break;
         case Instruction.ExecutionType.FloatingPoint:
             if (CPU.issueStage.fpStation.isFull()) return false;
             break;
         case Instruction.ExecutionType.Mem:
             if (CPU.issueStage.memStation.isFull()) return false;
             break;
         case Instruction.ExecutionType.MultDiv:
             if (CPU.issueStage.multDivStation.isFull()) return false;
             break;
         case Instruction.ExecutionType.Branch:
             if (CPU.issueStage.branchStation.isFull()) return false;
             break;
         case Instruction.ExecutionType.Nop:
             // Return True, as we do nto care about Nop
             break;
         default:
             System.Console.WriteLine("Decode Stage found Unknown Instruction Execution Type");
             break;
     }
     return true;
 }
예제 #8
0
        /// <summary>
        /// Checks to see if there is space in all appropriate buffers for the instruction
        /// </summary>
        /// <param name="instr">Instruction to be moved</param>
        /// <param name="issueStage">Issue Stage for instruction</param>
        /// <param name="rrf">Rename Register File</param>
        /// <returns>true if the system is ready, false otherwise</returns>
        private bool systemReadyForInstruction(Instruction instr)
        {
            //TODO: Check ROB
            if (CPU.rob.isFull())
            {
                Statistics.reorderBufferFull++;
                return false;
            }

            // Check to see if there is space available in the reservation stations
            if (this.isReservationStationAvaialble(instr) == false)
            {
                Statistics.reservationStationFull++;
                return false;
            }

            // Check to see if there is space available in the rrf
            if (CPU.rrf.spaceAvailable() == false)
            {
                Statistics.registerRenameFileFull++;
                return false;
            }

            return true;
        }
예제 #9
0
 /// <summary>
 /// Puts the instruction into the appropriate reservation station (located in the issue stage)
 /// </summary>
 private void dispatchToReservationStation(Instruction instr, int robTag)
 {
     switch (instr.executionType)
     {
         case Instruction.ExecutionType.Branch:
             CPU.issueStage.branchStation.ReceiveInstruction(instr, robTag);
             break;
         case Instruction.ExecutionType.FloatingPoint:
             CPU.issueStage.fpStation.ReceiveInstruction(instr, robTag);
             break;
         case Instruction.ExecutionType.Logical:
         case Instruction.ExecutionType.Integer:
             CPU.issueStage.integerStation.ReceiveInstruction(instr, robTag);
             break;
         case Instruction.ExecutionType.Mem:
             CPU.issueStage.memStation.ReceiveInstruction(instr, robTag);
             break;
         case Instruction.ExecutionType.MultDiv:
             CPU.issueStage.multDivStation.ReceiveInstruction(instr, robTag);
             break;
         case Instruction.ExecutionType.Nop:
             break;
     }
 }
예제 #10
0
        /// <summary>
        /// Puts the instruction into the reorder buffer
        /// </summary>
        ///  <returns>The tag of the entry used in the reorder buffer</returns>
        private int dispatchToReorderBuffer(Instruction instr)
        {
            CPU.rob.addEntry(instr);

            // TODO: We're using a queue for the ROB, so we don't really have a tag
            // to the entries within it. Do we have to change this?
            return -1;
        }
예제 #11
0
        /// <summary>
        /// Perform the Decode Stage
        /// 
        /// Checks to see if there is a stall on reading more instructions
        /// from the fetch stage due to a previously detected Branch Misprediction
        /// that has not completed the execute stage yet.
        /// 
        /// Then it checks the last two instructions in the fetch stage to see 
        /// if there is branch, and if it was predicted correctly.  This Enables
        /// a stall if necessary
        /// 
        /// Otherwise, copy instructions from the fetch stage
        /// 
        /// </summary>
        public void runCycle()
        {
            if(CPU.fetchStage.isEmpty() || this.isFull())
            {
                // Nothing to do here, fetch stage empty or we're full
                return;
            }

            // Make sure that we are not in a stall state waiting on
            // a branch instruction to finish executing
            if (CPU.branchMispredictionStall == false)
            {
                // Was the last instruction on the last cycle a branch? If yes, we need to check against our
                // member variable holding the info from that last instruction
                if (this.lastInstructionWasBranch == true)
                {
                    Instruction firstInstr = CPU.fetchStage.peekInstruction();
                    if (true == CPU.fetchStage.isBranchMispredict(this.lastInstruction, firstInstr))
                    {
                        //branch misprediction!
                        CPU.branchMispredictionStall = true;
                    }
                    else
                    {
                        // No misprediction between fetches, we're good to continue as normal
                    }
                    // Reset this
                    this.lastInstructionWasBranch = false;
                }

                // What we want here is to check each instruction one at a time to see if it's a branch instruction.
                // If it isn't, read it from the fetch buffer into the decode buffer.
                // If it is, is it the last instruction? If it's the last instruction, set our member variables
                // accordingly so we can check next time around
                while (!CPU.fetchStage.isEmpty())
                {
                    Instruction currInstr = CPU.fetchStage.getInstruction();
                    this.addInstructionToBuffer(currInstr);

                    if (!currInstr.isABranch())
                    {
                        if (this.isFull())
                            break;
                    }
                    else
                    {
                        // It's a branch; if it's the last instruction in the fetch buffer, we'll need to check
                        // for a mispredict next time around
                        if (CPU.fetchStage.isEmpty())
                        {
                            this.lastInstruction = currInstr;
                            this.lastInstructionWasBranch = true;
                        }
                        else
                        {
                            // It's not the last instruction, check for mispredict
                            if (true == CPU.fetchStage.isBranchMispredict(currInstr, CPU.fetchStage.peekInstruction()))
                            {
                                //branch misprediction!
                                CPU.branchMispredictionStall = true;
                            }

                            // We may be full now; if we are, break out
                            if (this.isFull())
                                break;
                        }
                    }
                }
                // We should have all the instructions from the fetch buffer now in the decode buffer
            } // End if(CPU.branchMispredictionStall == false)
        }
예제 #12
0
        /// <summary>
        /// Fetches as many instructions from the instruction trace as it can process
        /// up to super scalar width. Returns how many instructions it fetched.
        /// </summary>
        public int Fetch()
        {
            int numInstructionsRead = 0;
            int numSlotsOpen = 0;
            String line;
            Random rand = new Random();

            if (this.cacheMissed == false)
            {
                // We didn't miss the cache last time, so we have to see if we miss this time
                if (rand.Next(100) < Config.level1CacheInstrMissPercent)
                {
                    Statistics.level1InstrCacheMisses++;

                    //We did miss cache; set cacheMiss = true and the appropriate cacheMissCountdown
                    this.cacheMissed = true;
                    this.cacheMissCountdown = Config.level1CacheMissPenalty;

                    //Check for Level 2 Cache miss
                    if (rand.Next(100) < Config.level2CacheMissPercent)
                    {
                        Statistics.level2CacheMisses++;

                        //Update cache miss countdown to be main memory access plus the L2 access
                        this.cacheMissCountdown += Config.level2CacheMissPenalty;
                    }
                    return 0;
                }
            }
            else
            {
                // We did miss cache. If cacheMissCountdown is > 0, we have to wait more cycles, so we return.
                // Otherwise, we can move on and fetch.
                if (this.cacheMissCountdown > 0)
                {
                    this.cacheMissCountdown--;
                    return 0;
                }
            }

            numSlotsOpen = Config.superScalerFactor - this.fetchBuffer.Count;

            // Read in numSlotsOpen instructions from the trace file.
            for(int i = 0; i < numSlotsOpen; i++)
            {
                line = this.traceReader.ReadLine();
                if (line != null)
                {
                    numInstructionsRead++;
                    Instruction newInstruction = new Instruction(line);
                    CPU.pc = newInstruction.address;
                    CPU.pc_count++;
                    if(newInstruction.executionType != Instruction.ExecutionType.Nop)
                        fetchBuffer.Enqueue(newInstruction);
                }
                else
                {
                    // ensures that this is onle performed onces
                    if (CPU.lastInstructionFetched == false)
                    {
                        if (this.fetchBuffer.Count > 0)
                        {
                            fetchBuffer.Last().isLastInstruction = true;
                        }
                        else
                        {
                            CPU.decodeStage.decodeBuffer.Last().isLastInstruction = true;
                        }
                        CPU.lastInstructionFetched = true;
                    }
                }
            }

            // Reset cache miss
            this.cacheMissed = false;

            return numInstructionsRead;
        }
예제 #13
0
        /// <summary>
        /// Checks against two instructions to see if there is a branch mispredict
        /// </summary>
        /// <returns>true if there is was mispredict</returns>
        public bool isBranchMispredict(Instruction first, Instruction next)
        {
            if (!first.isABranch())
            {
                return false;
            }

            // If we got here, instr is a branch instruction
            bool branchPrediction = CPU.branchPredictor.predictBranch(first.address);
            bool actualResult;

            // if next pc == first pc +8 , branch not taken
            if (next.address == first.address + 8)
            {
                actualResult = false;
            }
            else
            {
                actualResult = true;
            }

            CPU.branchPredictor.updateBranchSM(first.address, branchPrediction, actualResult);

            // Fixed this...it's an isBranchMISpredict function,
            // so if branchPrediction != actualResult, you mispredicted--that is, return true
            return (branchPrediction != actualResult);
        }