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); }
private static void RenderMachineState(UrclMachine machine, bool allCores, Action <string> output) { output($"Cores: {machine.Cores.LongLength}, Word Mask: 0x{machine.BitMask:X}, RAM: {machine.RAM.LongLength} words, ROM: {machine.ROM.LongLength} words"); output($"Current Core: {machine.CurrentCore}"); if (allCores) { ulong i = 0; foreach (var core in machine.Cores) { RenderCoreState(i, core, output); i++; } } else { RenderCoreState(machine.CurrentCore, machine.Cores[machine.CurrentCore], output); } }
public Core(UrclMachine host, bool executeFromROM, ulong registers) { Host = host; ExecuteFromROM = executeFromROM; Registers = new ulong[registers]; }
public InvalidOperationException(UrclMachine machine, string message) : base(message) { MachineState = machine; }
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); }