private void Exec(TicTok tictok) { var cw = SEQ.Instance().ControlWord; // Both tied to the same signal from ram so when ram is emitting then MDR is changed as well if (string.Equals(cw["EM_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tic) { RegContent = ram.RegContent; } // LM_ is tied to MAR -> RAM so i did LR_ for MDR -> RAM if (string.Equals(cw["LR_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tic) { ram.SetWordAtMARAddress(RegContent); } // Active High, Push on Tic if (string.Equals(cw["EMDR"], "1", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tic) { //Wbus.Instance().Value = RegContent; Multiplexer.Instance().PassThroughToBus(RegContent, Convert.ToBoolean(Convert.ToInt16(cw["UB"])), Convert.ToBoolean(Convert.ToInt16(cw["CLR"]))); } // Active Low, Pull on Tok if (string.Equals(cw["LMDR_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tok) { //RegContent = Wbus.Instance().Value; RegContent = Multiplexer.Instance().PassThroughToRegister(Convert.ToBoolean(Convert.ToInt16(cw["UB"]))); } }
public void Exec(TicTok tictok) { var cw = SEQ.Instance().ControlWord; // Active Hi, Count on Tic if (string.Equals(cw["CP"], "1", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tic) { int count = BinConverter.Bin8ToInt(RegContent); count++; RegContent = BinConverter.IntToBin16(count); } // Active Hi, Push on Tic if (string.Equals(cw["EP"], "1", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tic) { // Send PC to the WBus Wbus.Instance().Value = RegContent; } // Active Low - Broadside Load, Pull if (string.Equals(cw["LP_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tok) { RegContent = Wbus.Instance().Value; } }
private void Exec(TicTok tictok) { var cw = SEQ.Instance().ControlWord; if (string.Equals(cw["CALL"], "1", StringComparison.Ordinal)) { // PC return address being set if (string.Equals(cw["RTNA"], "0", StringComparison.Ordinal)) { RegContent = Convert.ToString(0xFFFE - 0x0800 - 1, 2); ram.SetMARContent(RegContent); } else { RegContent = Convert.ToString(0xFFFF - 0x0800 - 1, 2); ram.SetMARContent(RegContent); } } // Active Low, Pull on Tok if (string.Equals(cw["LM_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tok) { // Store Wbus val in MAR RegContent = Wbus.Instance().Value; // Send the MAR data to the RAM ram.IncomingMARData(RegContent); } }
public void TestToString() { Clock clock = new Clock(); TicTok tictok = new TicTok(); tictok.Init();; int TState = 0; 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(); Frame frame = new Frame(ireg.ToString(), TState, areg, breg, ireg, mreg, oreg, pc, alu, ram.RAMDump(), ram, seq, Wbus.Instance().ToString(), Flags.Instance(), _decoder); _ = frame.ToString(); _ = frame.OutputRegister(); }
private void Exec(TicTok tictok) { var cw = SEQ.Instance().ControlWord; string aluResult = alu.RegContent; // Active Low, Pull on Tok if (aluResult[^ 1].Equals('1') && string.Equals(cw["LO_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tok)
public void TestToString() { Clock clock = new Clock(); TicTok tictok = new TicTok(); tictok.Init(); int TState = 0; AReg areg = new AReg(); TReg treg = new TReg(); BReg breg = new BReg(); CReg creg = new CReg(); IReg ireg = new IReg(); IPort1 port1 = new IPort1(); IPort2 port2 = new IPort2(); MDR mdr = new MDR(); RAM ram = new RAM(); mdr.SetRefToRAM(ref ram); ALU alu = new ALU(ref areg, ref treg); 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)); Instruction currentInstruction = new Instruction { OpCode = "ADD B", BinCode = "10000000", TStates = 4, AffectsFlags = true, AddressingMode = AddressingMode.Register, Bytes = 1 }; Frame frame = new Frame(currentInstruction, TState, port1, port2, pc, mar, ram, ram.RAMDump(), mdr, ireg, SEQ.Instance(), Wbus.Instance().Value, areg, alu, flagReg, treg, breg, creg, oreg3, oreg4, hexadecimalDisplay); _ = frame.ToString(); _ = frame.OutputRegister(); }
public void TestUnsubscribe() { 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(); seq.Load(GetInstructionSet()); 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); for (int i = 0; i < 500; i++) { clock.SendTicTok(tictok); tictok.ToggleClockState(); clock.SendTicTok(tictok); tictok.ToggleClockState(); } // UnSub all clock.EndTransmission(); for (int i = 0; i < 500; i++) { clock.SendTicTok(tictok); tictok.ToggleClockState(); clock.SendTicTok(tictok); tictok.ToggleClockState(); } }
private void Exec(TicTok tictok) { string cw = SEQ.Instance().ControlWord; // TODO - Find a better way of using the mask to get the value // Currently is using hardcoded magic numbers // Active Low, Pull on Tok if (cw[11] == '0' && tictok.ClockState == TicTok.State.Tok) { // Store Wbus val in A RegContent = Wbus.Instance().Value; } }
public void TestUpdate() { try { 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(); seq.Load(GetInstructionSet()); 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); clock.IsEnabled = true; for (int i = 0; i < 500; i++) { clock.SendTicTok(tictok); tictok.ToggleClockState(); clock.SendTicTok(tictok); tictok.ToggleClockState(); } } catch (Exception e) { Assert.Fail(e.ToString()); } }
private void Exec(TicTok tictok) { var cw = SEQ.Instance().ControlWord; // Active Hi, Push on Tic if (string.Equals(cw["ET"], "1", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tic) { // Send Temp to the WBus Multiplexer.Instance().PassThroughToBus(RegContent, Convert.ToBoolean(Convert.ToInt16(cw["UB"])), Convert.ToBoolean(Convert.ToInt16(cw["CLR"]))); } // Active Low, Pull on Tok if (string.Equals(cw["LT_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tok) { // Store Wbus val in Temp RegContent = Wbus.Instance().Value[8..];
private void Exec(TicTok tictok) { string cw = SEQ.Instance().ControlWord; // TODO - Find a better way of using the mask to get the value // Currently is using hardcoded magic numbers // Active Low, Pull on Tok if (cw[2] == '0' && tictok.ClockState == TicTok.State.Tok) { // Store Wbus val in A RegContent = Wbus.Instance().Value.Substring(4, 4); // Send the MAR data to the RAM ram.IncomingMARData(RegContent); } }
public void CheckForJumpCondition() { var cw = SEQ.Instance().ControlWord; string jumpType = cw["JC"]; WontJump = jumpType switch { "001" => flagReg.Signed, //JM "010" => flagReg.Zero, //JNZ "011" => !flagReg.Zero, //JZ "100" => true, "101" => true, "110" => true, "111" => true, _ => true }; }
private void Exec(TicTok tictok) { string cw = SEQ.Instance().ControlWord; // TODO - Find a better way of using the mask to get the value // Currently is using hardcoded magic numbers // Active Low, Push on Tic if (cw[5] == '0' & tictok.ClockState == TicTok.State.Tic) { // Send A to the WBus Wbus.Instance().Value = "0000" + RegContent.Substring(4, 4); //Instruction register only outputs the least significant bits to the WBus } // Active Low, Pull on Tok if (cw[4] == '0' && tictok.ClockState == TicTok.State.Tok) { RegContent = Wbus.Instance().Value; } }
public void TestControlWordTableInit() { SEQ.Instance().Load(GetInstructionSet()); const int INT_COUNT = 6; const int T_STATE_COUNT = 6; string[] INSTRUCTIONS = new string[6] { "0000", "0001", "0010", "0011", "1110", "1111" }; for (int instruction = 0; instruction < INT_COUNT; instruction++) { for (int tstate = 0; tstate < T_STATE_COUNT; tstate++) { string temp = INSTRUCTIONS[instruction]; // T States start at 1, not 0 Assert.AreNotEqual <string>(SEQ.Instance().UpdateControlWordReg(tstate + 1, temp), "", "Control Table not properly initialized"); } } }
private void Exec(TicTok tictok) { var cw = SEQ.Instance().ControlWord; // Active Hi, Push on Tic if (string.Equals(cw["EA"], "1", StringComparison.Ordinal) & tictok.ClockState == TicTok.State.Tic) { // Send A to the WBus while checking if we want to output to the bus upper or lower 8 bits Multiplexer.Instance().PassThroughToBus(RegContent, Convert.ToBoolean(Convert.ToInt16(cw["UB"])), Convert.ToBoolean(Convert.ToInt16(cw["CLR"]))); } // Active Low, Pull on Tok if (string.Equals(cw["LA_"], "0", StringComparison.Ordinal) && tictok.ClockState == TicTok.State.Tok) { // Special logic so we dont have immediate feedback when ALU -> A happens on the updated fetch cycle // Only applies to A Register if (string.Equals(cw["EU"], "1", StringComparison.Ordinal)) { return; } // Store Wbus val in A RegContent = Wbus.Instance().Value[8..];
// ************************************************************************* // ************************************************************************* // 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 }
public void Exec(TicTok tictok) { string cw = SEQ.Instance().ControlWord; // Active Hi, Count on Tic if (cw[0] == '1' && tictok.ClockState == TicTok.State.Tic) { int count = BinConverter.Bin8ToInt(RegContent); count++; RegContent = BinConverter.IntToBin8(count); } // Active Hi, Push on Tic if (cw[1] == '1' & tictok.ClockState == TicTok.State.Tic) { // Send A to the WBus Wbus.Instance().Value = RegContent; } // Active Low - Broadside Load, Pull if (cw[13] == '0' & tictok.ClockState == TicTok.State.Tok) { string count = Wbus.Instance().Value; if (count.Length >= 8) { count = "0000" + count.Substring(4, 4); } // The cw[14-16] is a 3-bit jump code that tells the PC which jump code to preform. // JMP == 000 // JEQ == 001 // JNQ == 010 // JLT == 011 // JGT == 100 // JIC == 101 string jump_code = cw.Substring(14, 3); // JMP if (jump_code == "000") { this.RegContent = count; } // JEQ else if (jump_code == "001") { if (areg.ToString() == "00000000") { this.RegContent = count; } } // JNQ else if (jump_code == "010") { if (areg.ToString() != "00000000") { this.RegContent = count; } } // JLT else if (jump_code == "011") { if (areg.ToString()[0] == '1') { this.RegContent = count; } } // JGT else if (jump_code == "100") { if (areg.ToString() != "00000000" && areg.ToString()[0] == '0') { this.RegContent = count; } } // JIC else if (jump_code == "101") { if (Flags.Instance().Overflow == 1) { this.RegContent = count; } } } }