public void TestRamContentsEmpty() { RAM ram = new RAM(); string[] ADDRS = new string[16] { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; try { List <string> RamContentsData = new List <string>(); RAMProgram rmp = new RAMProgram(RamContentsData); ram.LoadProgram(rmp); for (int i = 0; i < 15; i++) { // Since the RAMProgram was empty, the RAMProgam should fill will all zeros, so the RAM should be filled will all zeros. Assert.IsTrue(string.Equals(ram.GetWordAt(ADDRS[i]), "00000000")); } } catch (Exception e) { Assert.Fail(e.ToString()); } ram.ClearRAM(); }
public void TestRamContentFull() { RAM ram = new RAM(); string[] ADDRS = new string[16] { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; try { List <string> RamContentsData = new List <string> { "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101" }; RAMProgram rmp = new RAMProgram(RamContentsData); ram.LoadProgram(rmp); // Check to make sure the RAM entries and the list<string> share the same values for (int i = 0; i < 15; i++) { Assert.IsTrue(Equals(RamContentsData[i], ram.GetWordAt(ADDRS[i]))); } // Check to see it i == i+1, should be false for (int i = 0; i < 14; i++) { Assert.IsFalse(Equals(RamContentsData[i], ram.GetWordAt(ADDRS[i + 1]))); } } catch (Exception e) { Assert.Fail(e.ToString()); } ram.ClearRAM(); }
public void TestRamFull() { RAM ram = new RAM(); try { List <string> RamContentsData = new List <string> { "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "10101010", "01010101", "01010101", "01010101" }; RAMProgram rmp = new RAMProgram(RamContentsData); ram.LoadProgram(rmp); Assert.IsTrue(true); } catch (Exception e) { Assert.Fail(e.ToString()); } ram.ClearRAM(); }
// ************************************************************************* // ************************************************************************* // Engine Runtime // ************************************************************************* public void Run() { Clock clock = new Clock(); TicTok tictok = new TicTok(); tictok.Init(); AReg areg = new AReg(); TReg treg = new TReg(); BReg breg = new BReg(); CReg creg = new CReg(); IReg ireg = new IReg(); IPort1 iport1 = new IPort1(); IPort2 iport2 = new IPort2(); MDR mdr = new MDR(); RAM ram = new RAM(); mdr.SetRefToRAM(ref ram); ALU alu = new ALU(ref areg, ref treg); areg.SetALUReference(ref alu); breg.SetALUReference(ref alu); creg.SetALUReference(ref alu); OReg3 oreg3 = new OReg3(ref alu); OReg4 oreg4 = new OReg4(ref alu); HexadecimalDisplay hexadecimalDisplay = new HexadecimalDisplay(ref oreg3); Flag flagReg = new Flag(ref alu); PC pc = new PC(ref flagReg); MAR mar = new MAR(ref ram); SEQ seq = SEQ.Instance(); Wbus.Instance().Value = string.Concat(Enumerable.Repeat('0', 16)); areg.Subscribe(clock); treg.Subscribe(clock); breg.Subscribe(clock); creg.Subscribe(clock); ireg.Subscribe(clock); mar.Subscribe(clock); pc.Subscribe(clock); alu.Subscribe(clock); // ALU must come after A and T flagReg.Subscribe(clock); ram.Subscribe(clock); mdr.Subscribe(clock); oreg3.Subscribe(clock); hexadecimalDisplay.Subscribe(clock); oreg4.Subscribe(clock); // Load the program into the RAM ram.LoadProgram(Program); // Load the intsructionSet into the SEQ seq.Load(InstructionSet); Frame tempFrame; #region Program_Exec // Since T1-T3 for all of the Intruction is the same, // LDA or "0000" will be used as the intruction for all T1-T3's clock.IsEnabled = true; int max_loop_count = 10_000; int loop_counter = 0; int TState = 1; // A basic empty instruction state with 3 TStates since on the 4th the instruction // will be known and set to a new object reference. Instruction currentInstruction = new Instruction() { OpCode = "???", TStates = 4 // Since by 4 TStates it should know what instruction it is on }; List <string> controlWords = new List <string>(); bool? didntJump = null; while (clock.IsEnabled) { // Log the Instruction if (TState == 4) { currentInstruction = InstructionSet.Instructions.FirstOrDefault(i => i.BinCode.Equals(ireg.RegContent)); seq.LoadBackupControlWords(currentInstruction.MicroCode); string iname = currentInstruction.OpCode; int operandVal = Convert.ToInt32(ireg.RegContent, 2); string hexOperand = "0x" + operandVal.ToString("X"); } if (TState <= 3) { seq.UpdateControlWordReg(TState, "00000000", didntJump); if (didntJump ?? false) { pc.SkipByte(); didntJump = null; } } else { seq.UpdateControlWordReg(TState, ireg.RegContent); } clock.SendTicTok(tictok); tictok.ToggleClockState(); clock.SendTicTok(tictok); tictok.ToggleClockState(); tempFrame = new Frame(currentInstruction, TState, iport1, iport2, pc, mar, ram, ram.RAMDump(), mdr, ireg, SEQ.Instance(), Wbus.Instance().Value, areg, alu, flagReg, treg, breg, creg, oreg3, oreg4, hexadecimalDisplay); _FrameStack.Add(tempFrame); // HLT if (ireg.RegContent.Equals("01110110", StringComparison.Ordinal) && TState == 5) { clock.IsEnabled = false; _RAMDump = ram.RAMDump(); } if (loop_counter >= max_loop_count) { throw new EngineRuntimeException("Engine Error: Infinite Loop Detected"); } else { loop_counter++; } if (TState == 7 && currentInstruction.OpCode.StartsWith('J')) { pc.CheckForJumpCondition(); // PC is going to jump so do not let it fetch the next byte and immediately endx if (!pc.WontJump) { currentInstruction.TStates = 7; didntJump = true; } } if (TState < currentInstruction.TStates) { TState++; } else { TState = 1; currentInstruction = new Instruction() { OpCode = "???", TStates = 4 // Since by 4 TStates it should know what instruction it is on }; } } OutputReg = oreg3.ToString(); #endregion Program_Exec }
// ************************************************************************* // ************************************************************************* // Engine Runtime // ************************************************************************* public void Run() { //Log.Information("SAP1Emu: Begin Engine Run"); //Log.Verbose("SAP1Emu: Initializing Registers"); Clock clock = new Clock(); TicTok tictok = new TicTok(); tictok.Init(); AReg areg = new AReg(); BReg breg = new BReg(); IReg ireg = new IReg(); OReg oreg = new OReg(); RAM ram = new RAM(); PC pc = new PC(ref areg); ALU alu = new ALU(ref areg, ref breg); MReg mreg = new MReg(ref ram); SEQ seq = SEQ.Instance(); Wbus.Instance().Value = "00000000"; Flags.Instance().Clear(); areg.Subscribe(clock); breg.Subscribe(clock); ireg.Subscribe(clock); mreg.Subscribe(clock); oreg.Subscribe(clock); pc.Subscribe(clock); alu.Subscribe(clock); // ALU must come after A and B ram.Subscribe(clock); // Log.Verbose("SAP1Emu: Initialized Registers"); // Log.Information("SAP1Emu: Loading Ram"); // Load the program into the RAM ram.LoadProgram(Program); // Log.Information("SAP1Emu: RAM:\n{RAM}", Program.RamContents); // Load the intsructionSet into the SEQ seq.Load(InstructionSet); // Log.Information($"SAP1Emu: Loaded Instruction Set: \"{InstructionSet.SetName}\""); Frame tempFrame; #region Program_Exec // Since T1-T3 for all of the Intruction is the same, // LDA or "0000" will be used as the intruction for all T1-T3's clock.IsEnabled = true; // TODO: Cleanup old code stubs // These vars will make sure that the engine will not hang if there is an infinite loop // int warning1_loop_counter = 3000; // int warning2_loop_counter = 5000; // int warning3_loop_counter = 7000; // int warning4_loop_counter = 9000; int max_loop_count = 10000; int loop_counter = 0; int TState = 1; // Log.Information("SAP1Emu: Start Program Execution"); while (clock.IsEnabled) { if (TState <= 3) { seq.UpdateControlWordReg(TState, "0000"); } else { seq.UpdateControlWordReg(TState, ireg.ToString()); } // Log the Instruction if (TState == 4) { string iname = InstructionSet.Instructions.Find(x => x.BinCode.Equals(ireg.ToString())).OpCode; int operandVal = Convert.ToInt32(ireg.ToString_Frame_Use().Substring(4, 4), 2); string hexOperand = "0x" + operandVal.ToString("X"); // Log.Information($"SAP1Emu: Instruction: {iname}, Operand: {hexOperand}"); } clock.SendTicTok(tictok); tictok.ToggleClockState(); clock.SendTicTok(tictok); tictok.ToggleClockState(); tempFrame = new Frame(ireg.ToString(), TState, areg, breg, ireg, mreg, oreg, pc, alu, ram.RAMDump(), ram, seq, Wbus.Instance().ToString(), Flags.Instance(), _decoder, InstructionSet.SetName); _FrameStack.Add(tempFrame); if (ireg.ToString() == "1111" && TState == 6) { // Log.Information("SAP1Emu: HLT Detected"); clock.IsEnabled = false; } // Infinite Loop Checks //if(loop_counter == warning1_loop_counter) //{ // Log.Warning($"SAP1Emu: Infinite Loop Warning: interations count: {warning1_loop_counter} "); //} //else if (loop_counter == warning2_loop_counter) //{ // Log.Warning($"SAP1Emu: Infinite Loop Warning: interations count: {warning2_loop_counter} "); //} //else if (loop_counter == warning3_loop_counter) //{ // Log.Warning($"SAP1Emu: Infinite Loop Warning: interations count: {warning3_loop_counter} "); //} //else if (loop_counter == warning4_loop_counter) //{ // Log.Warning($"SAP1Emu: Infinite Loop Warning: interations count: {warning4_loop_counter} "); //} if (loop_counter >= max_loop_count) { // Log.Fatal($"SAP1Emu: Infinite Loop Fatal Error: Infinite Loop Detected"); // Log.CloseAndFlush(); throw new EngineRuntimeException("Engine Error: Infinite Loop Detected"); } else { loop_counter++; } if (TState < 6) { TState++; } else { TState = 1; } } // Log.Information("SAP1Emu: End Program Execution"); OutPutRegContents = oreg.ToString(); // Log.Information("SAP1Emu: End Engine Run"); // Log.CloseAndFlush(); #endregion Program_Exec }