Example #1
0
        public static void RunClock()
        {
            //Finished running if PC has exceeded instructions and all previous instructions have already finished running (determined by empty instruction queue)
            if (!IsReady || (PC.Counter >= Instructions.Count && InstructionQueue.Count == 0))
            {
                return;
            }

            AwaitingRegisters.Clear();
            ForwardedRegisters.Clear();

            if (PC.Counter < Instructions.Count && !_isStalled)
            {
                Instructions[PC.Counter].Initialize(_clockCycle);
                InstructionQueue.Enqueue(Instructions[PC.Counter]);
            }

            Instruction[] instructionQueueArray = InstructionQueue.ToArray();

            bool isJumpTaken = false;
            int  jumpIndex   = 0;

            _isStalled = false;

            //Run other stages for previous instructions in queue
            for (int i = 0; i < instructionQueueArray.Length; ++i)
            {
                Instruction instruction = instructionQueueArray[i];

                //If stall is needed do not advance any further instructions
                if (!instruction.AdvanceClock())
                {
                    _isStalled = true;
                    break;
                }

                //Mark register as awaiting values
                if (instruction.WriteAwaiting != -1)
                {
                    AwaitingRegisters.Add(instruction.WriteAwaiting);
                }

                //Add forwarded values
                if (instruction.ForwardedRegister.HasValue)
                {
                    ForwardedRegisters[instruction.WriteAwaiting] = instruction.ForwardedRegister.Value;
                }

                if (instruction.IsJumpTaken() && !isJumpTaken)
                {
                    var jumpData = instruction.GetJumpData();

                    if (jumpData.Type == Instruction.JumpType.Branch)
                    {
                        PC.Advance(jumpData.Address);
                    }
                    else if (jumpData.Type == Instruction.JumpType.Jump)
                    {
                        PC.Jump(jumpData.Address);
                    }

                    isJumpTaken = true;
                    jumpIndex   = i;
                }
            }

            //Discards instructions after jump or branch statement
            if (isJumpTaken)
            {
                InstructionQueue.Clear();

                for (int i = 0; i < jumpIndex; ++i)
                {
                    InstructionQueue.Enqueue(instructionQueueArray[i]);
                }
            }

            //Dequeue finished instructions
            if (instructionQueueArray[0].RelativeClock == 4)
            {
                InstructionQueue.Dequeue();
            }

            //If no jumps were taken advance program counter by 4
            if (!isJumpTaken && !_isStalled)
            {
                PC.Advance();
            }

            _clockCycle++;
        }