public static void Emulator(Configuration configuration, IEnumerable <UrclInstruction> instructions, Action <string> output, Action wait, bool allowConsole) { instructions = instructions.Append(new UrclInstruction(Operation.HLT)); var machine = new UrclMachine(1, configuration.Registers, configuration.AvailableMemory, configuration.AvailableROM, configuration.ExecuteOnROM, configuration.WordBitMask, allowConsole ? new ConsoleIO() : null); if (configuration.ExecuteOnROM) { machine.LoadROM(0, instructions); } else { machine.LoadRAM(0, instructions); } var start = Environment.TickCount64; var timeLimit = (long)configuration.MaxTime + start; var fault = false; while (!machine.Halted && (configuration.StepThrough || timeLimit - Environment.TickCount64 > 0)) { try { var brk = machine.Clock(); if ((brk && !configuration.DisableBreak) || configuration.StepThrough) { if (!configuration.StepThrough) { output("Breakpoint hit! System suspended."); output("Dumping machine state..."); } RenderMachineState(machine, configuration.StepThrough, output); output("Press any key to continue..."); wait?.Invoke(); } } catch (UrclMachine.InvalidOperationException ex) { output($"Fault! {ex.Message}"); fault = true; break; } } if (!machine.Halted && !fault) { output("Maximum time for execution was exceeded!"); } output($"System halted. Execution finished in {Environment.TickCount64 - start}ms ({machine.Ticks} ticks)."); output("Dumping final machine state..."); RenderMachineState(machine, true, output); }
public static void Emulator(Configuration configuration, IEnumerable <UrclInstruction> instructions, Action <string> output, Action wait, bool allowConsole) { ulong startAddress = 0; var wordSize = configuration.WordSize; instructions = instructions.Select(inst => { if (inst.Operation == Operation.BITS) { if (inst.A > 0 && inst.A <= configuration.WordSize) { wordSize = (ushort)inst.A; } } else if (inst.Operation == Operation.COMPILER_PRAGMA && inst.Arguments != null) { if (inst.Arguments.Length == 2) { var operand = inst.Arguments[1].ToLower(); switch (inst.Arguments[0].ToLower()) { case "org": if (Parser.TryParseValue(operand, out ulong v)) { startAddress = v; } else { throw new ParserError($"ORG pragma is not valid with parameter \"{operand}\"."); } break; } } } return(inst); }).Where(inst => inst.Operation != Operation.BITS).Append(new UrclInstruction(Operation.HLT)).ToArray(); var machine = new UrclMachine(1, configuration.Registers, configuration.MaxStack, configuration.AvailableMemory, configuration.AvailableROM, configuration.ExecuteOnROM, Configuration.GetBitMask(wordSize), allowConsole ? new ConsoleIO() : null); if (configuration.ExecuteOnROM) { machine.LoadROM(startAddress, instructions); } else { machine.LoadRAM(startAddress, instructions); } var start = Environment.TickCount64; var timeLimit = (long)configuration.MaxTime + start; var fault = false; while (!machine.Halted && (configuration.StepThrough || timeLimit - Environment.TickCount64 > 0)) { try { var brk = machine.Clock(); if ((brk && !configuration.DisableBreak) || configuration.StepThrough) { output(string.Empty); if (!configuration.StepThrough) { output("Breakpoint hit! System suspended."); output("Dumping machine state..."); } RenderMachineState(machine, configuration.StepThrough, output); output("Press any key to continue..."); wait?.Invoke(); } } catch (UrclMachine.InvalidOperationException ex) { output(string.Empty); output($"***Fault! {ex.Message}***"); fault = true; break; } } output(string.Empty); if (!machine.Halted && !fault) { output("Maximum time for execution was exceeded!"); } output($"System halted. Execution finished in {Environment.TickCount64 - start}ms ({machine.Ticks} ticks)."); output("Dumping final machine state..."); RenderMachineState(machine, true, output); }