public static void Add(this Instructions.AbstractInstruction[] ar, Instructions.AbstractInstruction i) { ar[0] = i; }
static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: ProgrammingAssignment /folder/file"); return(1); } // init global vars Globals.Cycles = 0; Globals.PC = 0; Globals.Misses = 0; Array.Clear(Globals.Registers, 0, Globals.Registers.Length); var InstructionList = new List <Instructions.AbstractInstruction>(); Instructions.AbstractInstruction[] Pipeline = new Instructions.AbstractInstruction[5]; Array.Clear(Pipeline, 0, Pipeline.Length); Array.Clear(Globals.Memory, 0, Globals.Memory.Length); Array.Clear(Globals.Cache, 0, Globals.Cache.Length); uint TotalInstr = 0; uint Cycles = 0; // preprocessing string text = ""; try { text = File.ReadAllText(args[0]); } catch { Console.WriteLine("Error reading file"); return(1); } var cr = new CommentRemoval(text); text = cr.RemoveComments(); var asgn = new AssignmentExtractor(text); text = asgn.ExtractAssignment(); var le = new LabelExtractor(text); text = le.ExtractLabels(); var pr = new PrintExtractor(text); var prints = pr.ExtractPrints(); // reading commands using (StringReader reader = new StringReader(text)) { string line; while ((line = reader.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line) || line.StartsWith("PRINT")) { continue; } InstructionList.Add(Instructions.InstructionFactory.GetInstruction(line)); } } // execute // TODO: // ld x1 x2 // brl x1 Label Pipeline.Add(InstructionList[Globals.PC++]); while (!Pipeline.IsEmpty()) { Globals.Cycles++; // resolve branch target on stage 2: if (Pipeline[1] != null) { var t = Pipeline[1].GetType(); if (t == typeof(Instructions.Brg) || t == typeof(Instructions.Brl) || t == typeof(Instructions.Brnz) || t == typeof(Instructions.Brz)) { int pc = Globals.PC; // data forward from prev. instr. int?res; try { res = null; // find among previous instr. if any os them used the target register int i = 2; while (i < 5 && Pipeline[i] != null) { if (Pipeline[i].GetTargetRegister() == Pipeline[1].GetTargetRegister()) { res = Pipeline[i].Peek(); break; } i++; } if (res.HasValue) // if a previous instr. used target register of the branch { (Pipeline[1] as Instructions.OneOperandConstantInstruction).ComputeInAdvance(res.Value); if (pc != Globals.PC) // if taken { Globals.Cycles++; // replace the next instruction with correct one Pipeline.Add(InstructionList[Globals.PC++]); } } } catch (NotImplementedException) { // preceeding ld, ldi, st, sti instr. // cannot data forward } } } // detect data hazards // ld x1, 0(x2) // sub x4, x1, x5 if (Pipeline[0] != null && Pipeline[1] != null && (Pipeline[1].GetType() == typeof(Instructions.Ld) || Pipeline[1].GetType() == typeof(Instructions.Ldi))) { int reg = (Pipeline[1] as Instructions.AbstractInstruction).GetTargetRegister(); int?[] operands = new int?[2]; (Pipeline[0] as Instructions.AbstractInstruction).GetOperands(ref operands); int i = -1; int?op; while ((op = operands[++i]) != null) { if (op.Value == reg) // we have a stall { Globals.Cycles++; break; } } } if (Pipeline[4] != null) { try { Pipeline[4].Compute(); } catch (DivideByZeroException) { Console.WriteLine("A division of zero occured. Aborting"); break; } TotalInstr++; } Pipeline.Shift(); if (Globals.PC <= InstructionList.Count - 1) { Pipeline.Add(InstructionList[Globals.PC++]); } } // to prevent overwriting Cycles = Globals.Cycles; // printing // TODO: Do print statements incur any cycle overhead? if (prints.Item1.Count != 0) { Console.WriteLine("REGISTERS:"); } foreach (var elem in prints.Item1) { Console.WriteLine(Globals.Registers[elem]); } if (prints.Item2.Count != 0) { Console.WriteLine("MEMORY:"); } foreach (var elem in prints.Item2) { Console.WriteLine(MemoryManager.Load(elem)); } Console.WriteLine($"Total # of instructions executed: {TotalInstr}"); Console.WriteLine($"Total # of cycles: {Cycles}"); Console.WriteLine("Average # of cycles per instruction: {0:F2}", (float)Cycles / (float)TotalInstr); Console.WriteLine($"Total # of misses: {Globals.Misses}"); Console.WriteLine("Misses per instruction: {0:F2}", (float)Globals.Misses / (float)TotalInstr); Console.ReadKey(); return(0); }