public void PerformStore() { while (!areWeDone) { storeEvent.WaitOne(); Console.WriteLine("In Store"); if (executed_instructions.Count > 0) { ExecutedInstruction instrResult = executed_instructions.Dequeue(); Console.WriteLine("Store dequeued: " + Memory.getAssemblyInstructions().ElementAt(instrResult.instrIndex)); if (instrResult.type == StoreType.Accumulator) { ACC = instrResult.result; } else if (instrResult.type == StoreType.Memory) { memory[instrResult.memoryIndex] = instrResult.result; Console.WriteLine("Stored " + instrResult.result + " into memory index " + instrResult.memoryIndex); } //Console.WriteLine("Performed store on: " + binary); PC++; Console.WriteLine("PC is: " + PC + " and Fetch counter is: " + Fetch_Counter); if (OnStoreDone != null) { Console.WriteLine("Stored: " + Memory.getAssemblyInstructions().ElementAt(instrResult.instrIndex) + "--------------"); OnStoreDone(this, new StoreEventArgs(instrResult.instrIndex, false)); //OnStoreDone(this, new StageDoneEventArgs(instrResult.instrIndex, StageType.Store)); } /*if (OnStageDone != null) * { * OnStageDone(this, new StageDoneEventArgs(StageType.Store)); * }*/ //Store_Counter++; } CPU_OnStageDone(StageType.Store); if ((Fetch_Counter == Memory.getBinaryInstructions().Count()) && (executed_instructions.Count == 0) && (decoded_instructions.Count == 0) && (fetched_instructions.Count == 0) && instrExecute == null) { //this means we just stored the final instruction, so increment PC to trip the end of the program //PC++; Console.WriteLine("PROGRAM DONE"); OnStoreDone(this, new StoreEventArgs(-1, true)); } //CPU_OnStageDone(StageType.Store); } }
public void executeInstruction(DecodedInstruction instr) { //PC++; string binaryString = Convert.ToString(instr.binary, 2).PadLeft(16, '0'); String opcode = instr.opcode; String command = instr.command; String flag = instr.flag; short value = instr.value; int instrIndex = instr.index; //Defaults to none for things like NOP and branches ExecutedInstruction executedInstr = new ExecutedInstruction(0, StoreType.None, instrIndex); Console.WriteLine("Executing ---->" + binaryString + " O " + opcode + " C " + command + " F " + flag + " V " + value); switch (opcode) { case "000": // --------------GROUP1 if (command == "0000") // NOP { Debug.WriteLine("NOP has been reached"); //return; } else // HLT //DO HLT { Debug.WriteLine("HLT has been reached"); //return; } break; case "001": // ------------GROUP2 if (command == "0001") //LDA //Maybe signal to the GUI here that there was a load-use delay { if (!bypassing) { //penalty for a load-use delay is 1 cycle cycle_penalties++; } if (flag == "1") { //# Debug.WriteLine("LDA# has been reached"); //ACC = value; executedInstr = new ExecutedInstruction(value, StoreType.Accumulator, instrIndex); } else { //$ Debug.WriteLine("LDA$ has been reached"); //ACC = Memory.stack[value]; //ACC = memory[value]; executedInstr = new ExecutedInstruction(memory[value], StoreType.Accumulator, instrIndex); } } if (command == "0010") //STA { Debug.WriteLine("STA has been reached"); //Memory.stack[value] = ACC; //memory[value] = ACC; executedInstr = new ExecutedInstruction(ACC, StoreType.Memory, instrIndex, value); Debug.Write("Stored the value " + ACC + " into stack at index " + value); } else if (command == "1010") { Debug.WriteLine("STA special has been reached"); TEMP = ACC; Debug.WriteLine("TEMP = " + TEMP); } break; case "010": // --------------GROUP3 if (command == "0001") //ADD { if (flag == "1") { //# Debug.WriteLine("ADD# has been reached"); Debug.Write("Value is " + value); //ACC += value; executedInstr = new ExecutedInstruction(ACC + value, StoreType.Accumulator, instrIndex); Debug.Write(" ACC is " + ACC); } else { //$ Debug.WriteLine("ADD$ has been reached"); //ACC += Memory.stack[value]; //ACC += memory[value]; executedInstr = new ExecutedInstruction(ACC + memory[value], StoreType.Accumulator, instrIndex); } break; } if (command == "1001") //Special add { Debug.WriteLine("Special ADD has been reached"); ACC += TEMP; } if (command == "0010") // SUB { if (flag == "1") { //# Debug.WriteLine("SUB# has been reached"); Debug.WriteLine("ACC is " + ACC + " and value is " + value); //ACC -= value; executedInstr = new ExecutedInstruction(ACC - value, StoreType.Accumulator, instrIndex); Debug.WriteLine("ACC is now " + ACC); } else { //$ //int temp = Memory.stack[value]; //int temp1 = memory[value]; Debug.WriteLine("SUB$ has been reached"); //Debug.WriteLine("ACC is " + ACC + " and value is " + temp1); //ACC -= temp; executedInstr = new ExecutedInstruction(ACC - memory[value], StoreType.Accumulator, instrIndex); Debug.WriteLine("ACC is now " + ACC); } } if (command == "0011") //MUL //maybe signal to the GUI that there was a hazard { cycle_penalties = cycle_penalties + 4; mdHazard = true; if (flag == "1") { //# Debug.WriteLine("MUL# has been reached"); //ACC = ACC * value; executedInstr = new ExecutedInstruction(ACC * value, StoreType.Accumulator, instrIndex); } else { //$ Debug.WriteLine("MUL$ has been reached"); //ACC = ACC * Memory.stack[value]; //ACC = ACC * memory[value]; executedInstr = new ExecutedInstruction(ACC * memory[value], StoreType.Accumulator, instrIndex); } } if (command == "0100") //DIV //maybe signal to the GUI that there was a hazard { cycle_penalties = cycle_penalties + 4; mdHazard = true; if (flag == "1") { //# Debug.WriteLine("DIV# has been reached"); //ACC = ACC / value; executedInstr = new ExecutedInstruction(ACC / value, StoreType.Accumulator, instrIndex); } else { //$ Debug.WriteLine("DIV$ has been reached"); //ACC = ACC / Memory.stack[value]; //ACC = ACC / memory[value]; executedInstr = new ExecutedInstruction(ACC / memory[value], StoreType.Accumulator, instrIndex); } } if (command == "0101") //SHL //SHL things { Debug.WriteLine("SHL has been reached"); ACC = ACC << value; } break; case "011": //-----------------GROUP4 if (command == "0001") //AND { if (flag == "1") { //# Debug.WriteLine("AND# has been reached"); //ACC = ACC & value; executedInstr = new ExecutedInstruction(ACC & value, StoreType.Accumulator, instrIndex); } else { //$ //int temp = Memory.stack[value]; //int temp = memory[value]; Debug.WriteLine("AND$ has been reached"); //Debug.WriteLine("ACC is " + ACC + " and value is " + temp); //ACC = ACC & temp; executedInstr = new ExecutedInstruction(ACC & memory[value], StoreType.Accumulator, instrIndex); Debug.WriteLine("ACC is now " + ACC); } } if (command == "0010") //OR { if (flag == "1") { //# Debug.WriteLine("OR# has been reached"); //ACC = ACC | (ushort)value; // Do we need to cast here? perhaps executedInstr = new ExecutedInstruction(ACC | (ushort)value, StoreType.Accumulator, instrIndex); } else { //$ Debug.WriteLine("OR$ has been reached"); //ACC = ACC | Memory.stack[value]; //ACC = ACC | memory[value]; executedInstr = new ExecutedInstruction(ACC | memory[value], StoreType.Accumulator, instrIndex); } } if (command == "0011") //NOTA //NOTA things { Debug.WriteLine("NOTA# has been reached"); Debug.WriteLine("!" + ACC + " is " + ~ACC); //ACC = ~ACC; // I think ~ is a bitwise not executedInstr = new ExecutedInstruction(~ACC, StoreType.Accumulator, instrIndex); } break; case "100": // ------------------GROUP5 tookBranch = false; if (command == "0001") //BA { Debug.WriteLine("BA has been reached"); tookBranch = true; } if (command == "0010") //BE { Debug.WriteLine("BE has been reached"); if (CC == 0) { tookBranch = true; } } if (command == "0011") //BL { Debug.WriteLine("BL has been reached"); if (CC < 0) { tookBranch = true; } } if (command == "0100") //BG { Debug.WriteLine("BG has been reached"); if (CC > 0) { tookBranch = true; } } foreach (var branch in branches) { if (branch.branchlabel.CompareTo(Memory.getAssemblyInstructions().ElementAt(instrIndex)) == 0) { branch.numTaken++; branch.updateChoice(tookBranch); } } if (tookBranch) { //Normal branching code PC = (short)(value - 1); //think it was -1 due to the PC incrementing after// PC = (short)(value - 1); Fetch_Counter = PC + 1; Decode_Counter = -1; //PC Execute_Counter = -1; //PC fetched_instructions.Clear(); decoded_instructions.Clear(); executed_instructions.Clear(); //penalty for a taken branch is 1 cycle cycle_penalties++; //gotta call something here to flush out pipeline queue in GUI //moved to execute thread if (OnBranch != null) { OnBranch(this, new BranchEventArgs(instr, instrIndex, true)); //OnFetchDone(this, new FetchEventArgs(0, -1)); //OnDecodeDone(this, new DecodeEventArgs(null, -1)); //OnExecuteDone(this, new ExecuteEventArgs(0, -1)); } } else { if (OnBranch != null) { OnBranch(this, new BranchEventArgs(instr, instrIndex, false)); } } break; } //This is to avoid the next instruction being a branch and depending on the //cc to be updated from the previous instruction when it goes to store if (executedInstr.type == StoreType.Accumulator) { if (executedInstr.result > 0) { CC = 1; } else if (executedInstr.result < 0) { CC = -1; } else { CC = 0; } } //Passes the result of execute to the store stage, to be stored next cycle executed_instructions.Enqueue(executedInstr); return; }
public void executeInstruction(DecodedInstruction instr) { //PC++; string binaryString = Convert.ToString(instr.binary, 2).PadLeft(16, '0'); String opcode = instr.opcode; String command = instr.command; String flag = instr.flag; short value = instr.value; int instrIndex = instr.index; //Defaults to none for things like NOP and branches ExecutedInstruction executedInstr = new ExecutedInstruction(0, StoreType.None, instrIndex); Console.WriteLine("Executing ---->" + binaryString + " O " + opcode + " C " + command + " F " + flag + " V " + value); switch (opcode) { case "000":// --------------GROUP1 if(command == "0000"){ // NOP Debug.WriteLine("NOP has been reached"); //return; } else{ // HLT //DO HLT Debug.WriteLine("HLT has been reached"); //return; } break; case "001":// ------------GROUP2 if(command == "0001"){ //LDA //Maybe signal to the GUI here that there was a load-use delay if (!bypassing) { //penalty for a load-use delay is 1 cycle cycle_penalties++; } if(flag == "1"){ //# Debug.WriteLine("LDA# has been reached"); //ACC = value; executedInstr = new ExecutedInstruction(value, StoreType.Accumulator, instrIndex); } else{ //$ Debug.WriteLine("LDA$ has been reached"); //ACC = Memory.stack[value]; //ACC = memory[value]; executedInstr = new ExecutedInstruction(memory[value], StoreType.Accumulator, instrIndex); } } if(command == "0010"){ //STA Debug.WriteLine("STA has been reached"); //Memory.stack[value] = ACC; //memory[value] = ACC; executedInstr = new ExecutedInstruction(ACC, StoreType.Memory, instrIndex, value); Debug.Write("Stored the value " + ACC + " into stack at index " + value); } else if(command == "1010"){ Debug.WriteLine("STA special has been reached"); TEMP = ACC; Debug.WriteLine("TEMP = " + TEMP); } break; case "010":// --------------GROUP3 if(command == "0001"){ //ADD if(flag == "1"){ //# Debug.WriteLine("ADD# has been reached"); Debug.Write("Value is " + value); //ACC += value; executedInstr = new ExecutedInstruction(ACC + value, StoreType.Accumulator, instrIndex); Debug.Write(" ACC is " + ACC); } else{ //$ Debug.WriteLine("ADD$ has been reached"); //ACC += Memory.stack[value]; //ACC += memory[value]; executedInstr = new ExecutedInstruction(ACC + memory[value], StoreType.Accumulator, instrIndex); } break; } if (command == "1001")//Special add { Debug.WriteLine("Special ADD has been reached"); ACC += TEMP; } if(command == "0010"){ // SUB if(flag == "1"){ //# Debug.WriteLine("SUB# has been reached"); Debug.WriteLine("ACC is " + ACC + " and value is " + value); //ACC -= value; executedInstr = new ExecutedInstruction(ACC - value, StoreType.Accumulator, instrIndex); Debug.WriteLine("ACC is now " + ACC); } else{ //$ //int temp = Memory.stack[value]; //int temp1 = memory[value]; Debug.WriteLine("SUB$ has been reached"); //Debug.WriteLine("ACC is " + ACC + " and value is " + temp1); //ACC -= temp; executedInstr = new ExecutedInstruction(ACC - memory[value], StoreType.Accumulator, instrIndex); Debug.WriteLine("ACC is now " + ACC); } } if(command == "0011"){//MUL //maybe signal to the GUI that there was a hazard cycle_penalties = cycle_penalties + 4; mdHazard = true; if(flag == "1"){ //# Debug.WriteLine("MUL# has been reached"); //ACC = ACC * value; executedInstr = new ExecutedInstruction(ACC * value, StoreType.Accumulator, instrIndex); } else{ //$ Debug.WriteLine("MUL$ has been reached"); //ACC = ACC * Memory.stack[value]; //ACC = ACC * memory[value]; executedInstr = new ExecutedInstruction(ACC * memory[value], StoreType.Accumulator, instrIndex); } } if(command == "0100"){//DIV //maybe signal to the GUI that there was a hazard cycle_penalties = cycle_penalties + 4; mdHazard = true; if(flag == "1"){ //# Debug.WriteLine("DIV# has been reached"); //ACC = ACC / value; executedInstr = new ExecutedInstruction(ACC / value, StoreType.Accumulator, instrIndex); } else{ //$ Debug.WriteLine("DIV$ has been reached"); //ACC = ACC / Memory.stack[value]; //ACC = ACC / memory[value]; executedInstr = new ExecutedInstruction(ACC / memory[value], StoreType.Accumulator, instrIndex); } } if(command == "0101"){//SHL //SHL things Debug.WriteLine("SHL has been reached"); ACC = ACC << value; } break; case "011": //-----------------GROUP4 if(command == "0001"){//AND if(flag == "1"){ //# Debug.WriteLine("AND# has been reached"); //ACC = ACC & value; executedInstr = new ExecutedInstruction(ACC & value, StoreType.Accumulator, instrIndex); } else{ //$ //int temp = Memory.stack[value]; //int temp = memory[value]; Debug.WriteLine("AND$ has been reached"); //Debug.WriteLine("ACC is " + ACC + " and value is " + temp); //ACC = ACC & temp; executedInstr = new ExecutedInstruction(ACC & memory[value], StoreType.Accumulator, instrIndex); Debug.WriteLine("ACC is now " + ACC); } } if(command == "0010"){//OR if(flag == "1"){ //# Debug.WriteLine("OR# has been reached"); //ACC = ACC | (ushort)value; // Do we need to cast here? perhaps executedInstr = new ExecutedInstruction(ACC | (ushort)value, StoreType.Accumulator, instrIndex); } else{ //$ Debug.WriteLine("OR$ has been reached"); //ACC = ACC | Memory.stack[value]; //ACC = ACC | memory[value]; executedInstr = new ExecutedInstruction(ACC | memory[value], StoreType.Accumulator, instrIndex); } } if(command == "0011"){//NOTA //NOTA things Debug.WriteLine("NOTA# has been reached"); Debug.WriteLine("!" + ACC + " is " + ~ACC); //ACC = ~ACC; // I think ~ is a bitwise not executedInstr = new ExecutedInstruction(~ACC, StoreType.Accumulator, instrIndex); } break; case "100": // ------------------GROUP5 tookBranch = false; if (command == "0001"){//BA Debug.WriteLine("BA has been reached"); tookBranch = true; } if(command == "0010"){//BE Debug.WriteLine("BE has been reached"); if (CC == 0) { tookBranch = true; } } if(command == "0011"){//BL Debug.WriteLine("BL has been reached"); if (CC < 0) { tookBranch = true; } } if (command == "0100"){//BG Debug.WriteLine("BG has been reached"); if (CC > 0) { tookBranch = true; } } foreach (var branch in branches) { if (branch.branchlabel.CompareTo(Memory.getAssemblyInstructions().ElementAt(instrIndex)) == 0) { branch.numTaken++; branch.updateChoice(tookBranch); } } if (tookBranch) { //Normal branching code PC = (short)(value-1);//think it was -1 due to the PC incrementing after// PC = (short)(value - 1); Fetch_Counter = PC+1; Decode_Counter = -1;//PC Execute_Counter = -1;//PC fetched_instructions.Clear(); decoded_instructions.Clear(); executed_instructions.Clear(); //penalty for a taken branch is 1 cycle cycle_penalties++; //gotta call something here to flush out pipeline queue in GUI //moved to execute thread if (OnBranch != null) { OnBranch(this, new BranchEventArgs(instr, instrIndex, true)); //OnFetchDone(this, new FetchEventArgs(0, -1)); //OnDecodeDone(this, new DecodeEventArgs(null, -1)); //OnExecuteDone(this, new ExecuteEventArgs(0, -1)); } } else { if (OnBranch != null) { OnBranch(this, new BranchEventArgs(instr, instrIndex, false)); } } break; } //This is to avoid the next instruction being a branch and depending on the //cc to be updated from the previous instruction when it goes to store if (executedInstr.type == StoreType.Accumulator) { if (executedInstr.result > 0) { CC = 1; } else if (executedInstr.result < 0) { CC = -1; } else CC = 0; } //Passes the result of execute to the store stage, to be stored next cycle executed_instructions.Enqueue(executedInstr); return; }