/****************************************************** * CALL: reset(); * TASK: Sets the member variables to their initiated value. *****************************************************/ public void reset() { _output = new Bit12(0); _instructionPtr = 0; _workingRegister = new Bit12(0); resetMemory(); }
/****************************************************** * CALL: bool ok = addrIdxToUpdate(Bit12, out byte); * TASK: Handles indexing of STORE, CALL and RETURN * instructions. *****************************************************/ public bool addrIdxToUpdate(Bit12 command, out byte idx) { byte val = (byte)extractVal(command.value()); Operations opr = Operations.LOAD; if (!extractOperation(command.value(), out opr)) { idx = 0; return(false); } switch (opr) { case Operations.STORE: { idx = (byte)(val); return(true); } case Operations.CALL: { idx = (byte)(255 - _memoryStack.size()); return(true); } case Operations.RETURN: { idx = (byte)(255 - _memoryStack.size() - 1); return(true); } default: { idx = 0; return(false); } } }
/****************************************************** * CALL: bool ok = stringToMachine(string, out Bit12); * TASK: Converts the string to machine code and returns * true if doing so successfully. *****************************************************/ public bool stringToMachine(string str, out Bit12 machineCode) { if (string.IsNullOrWhiteSpace(str)) { machineCode = new Bit12(0); return(true); } bool binary = isBinary(str); if (binary && str.Length == 12) { machineCode = new Bit12(Convert.ToInt16(str, 2)); return(true); } else { if (!assemblyToMachine(str, out machineCode)) { machineCode = new Bit12(0); return(false); } return(true); } }
/****************************************************** * CALL: Clicking the step back button. * TASK: Rolls back the program one step i.e. undo the * previous operation. *****************************************************/ private void Button_StepBack_Click(object sender, RoutedEventArgs e) { if (_runTimer.IsEnabled) { errorCode("Cannot undo while running the application."); return; } if (_assemblerModel.undoStack().size() == 0) { errorCode("Nothing to undo."); return; } if (_assemblerModel.undoStack().size() == 1) { Keyboard.ClearFocus(); _currentTextBox.Foreground = (Brush)FindResource("TextBoxForegroundOff"); clearUserMsg(); _currentTextBox.IsReadOnly = false; showButtonAsEnabled(ButtonType.Stop); } UndoStorage undoValues = _assemblerModel.undo(); Bit12 currentAddr = _assemblerModel.getAddr(_assemblerModel.instructionPtr()); Operations opr = Operations.LOAD; _assemblerModel.extractOperation(currentAddr.value(), out opr); // Mark current row markRow(getMMRowOfPosition(255 - _assemblerModel.instructionPtr())); // Update graphics of changed memory byte index; if (_assemblerModel.addrIdxToUpdate(currentAddr, out index)) { if (opr == Operations.RETURN) { index += 2; } MemoryRow row = getMMRowOfPosition(255 - index); row.ShowMemoryAdress(_assemblerModel.getAddr(index)); if (index > 250) { MemoryRow stackRow = getStackRowOfPosition(255 - index); stackRow.ShowMemoryAdress(_assemblerModel.getAddr(index)); } } ValueRow_WorkingRegister.ShowMemoryAdress(_assemblerModel.workingRegister()); ValueRow_Output.ShowMemoryAdress(_assemblerModel.output()); lightIfOutputIsOn(); ValueRow_InstructionPointer.ShowMemoryAdress(new Bit12(_assemblerModel.instructionPtr())); }
/****************************************************** * CALL: programTick(); * TASK: Progresses the execution of the program * one instruction. *****************************************************/ private void programTick() { Bit12 currentAddr = _assemblerModel.getAddr(_assemblerModel.instructionPtr()); Operations opr; byte val = (byte)_assemblerModel.extractVal(currentAddr.value()); _assemblerModel.extractOperation(currentAddr.value(), out opr); if (opr == Operations.RETURN && _assemblerModel.stack().size() == 0) { errorCode("Attempted Return on an empty stack."); pauseProgram(); return; } if (!_assemblerModel.processCurrentAddr()) { errorCode("Invalid operation."); pauseProgram(); return; } // Mark current row markRow(getMMRowOfPosition(255 - _assemblerModel.instructionPtr())); // Update graphics of changed memory byte index; if (_assemblerModel.addrIdxToUpdate(currentAddr, out index)) { if (opr != Operations.STORE) { index++; } MemoryRow row = getMMRowOfPosition(255 - index); row.ShowMemoryAdress(_assemblerModel.getAddr(index)); if (index > 250) { MemoryRow stackRow = getStackRowOfPosition(255 - index); stackRow.ShowMemoryAdress(_assemblerModel.getAddr(index)); } } ValueRow_WorkingRegister.ShowMemoryAdress(_assemblerModel.workingRegister()); ValueRow_Output.ShowMemoryAdress(_assemblerModel.output()); ValueRow_InstructionPointer.ShowMemoryAdress(new Bit12(_assemblerModel.instructionPtr())); //First bit on output sets the light lightIfOutputIsOn(); }
/****************************************************** * CALL: resetMemory(); * TASK: Resets the memory. *****************************************************/ public void resetMemory() { for (int i = 0; i < _size; i++) { _memory[i] = new Bit12(0); } while (_memoryStack.size() > 0) { _memoryStack.pop(); } while (_undoStack.size() > 0) { _undoStack.pop(); } }
public UndoStorage(Bit12[] memory , MyStack <Bit12> memoryStack , byte instructionPtr , Bit12 workingRegister , Bit12 input , Bit12 output) { _memory = new Bit12[memory.Length]; _memoryStack = new MyStack <Bit12>(_memory); Array.Copy(memory, _memory, memory.Length); for (int i = 0; i < memoryStack.size(); i++) { _memoryStack.push(_memory[255 - i]); } _instructionPtr = instructionPtr; _workingRegister = workingRegister; _output = output; }
public AssemblerModel() { _size = 256; // Leave this at 256 (many of our attributes are 8 bit) _memory = new Bit12[_size]; for (int i = 0; i < _size; i++) { _memory[i] = new Bit12(0); } _memoryStack = new MyStack <Bit12>(_memory); _undoStack = new CircularStack <UndoStorage>(1000); _instructionPtr = 0; _workingRegister = new Bit12(0); _input = new Bit12(0); _output = new Bit12(0); _labels = new Dictionary <string, byte>(); resetMemory(); }
/****************************************************** * CALL: bool ok = binaryStringToMachine(string, out Bit12); * TASK: Returns true if the parameter string was converted * to Bit12 machine code successfully. *****************************************************/ public bool binaryStringToMachine(string str, out Bit12 machineCode) { if (string.IsNullOrWhiteSpace(str)) { machineCode = new Bit12(0); return(true); } bool binary = isBinary(str); if (!binary || str.Length != 12) { machineCode = new Bit12(0); return(false); } machineCode = new Bit12(Convert.ToInt16(str, 2)); return(true); }
/****************************************************** * CALL: updateGUIMemory(byte, byte, TextBox); * TASK: Updates the graphics of the different parts * of the memory. *****************************************************/ private void updateGUIMemory(byte from, byte to, TextBox textBox) { for (int i = from; i <= to; i++) { string str = ""; if (i < textBox.LineCount) { str = textBox.GetLineText(i); } char[] trimChars = new char[3] { '\r', '\n', ' ' }; str = str.TrimEnd(trimChars); Bit12 val = new Bit12(0); if (!string.IsNullOrWhiteSpace(str)) { if (textBox == TextBox_Assembler) { _assemblerModel.assemblyToMachine(str, out val); } else { if (_assemblerModel.checkSyntaxMachine(str)) { short tempval = Convert.ToInt16(str, 2); val = new Bit12(tempval); } } } if (i > 250) { MemoryRow stackRow = getStackRowOfPosition(255 - i); stackRow.ShowMemoryAdress(val); } MemoryRow rad = getMMRowOfPosition(255 - i); rad.ShowMemoryAdress(val); } }
/****************************************************** * CALL: ShowMemoryAdress(); * TASK: Prints a row of ones and zeros in the memory. *****************************************************/ public void ShowMemoryAdress(Bit12 val) { UniformGrid memoryGrid = this.BinaryMemoryAdress as UniformGrid; string str = Convert.ToString(val.value(), 2).PadLeft(12, '0'); if (str.Length > 12) { str = str.Substring(str.Length - 12); } for (int i = 0; i < str.Length && i < memoryGrid.Children.Count; i++) { Label lab = memoryGrid.Children[i] as Label; if (str[i] == '0' || str[i] == '1') { lab.Content = str[i]; } } }
/****************************************************** * CALL: bool ok = checkSyntaxAssemblyTextBox(TextBox); * TASK: Checks if any line entered in the assembler * section contains unapproved characters. *****************************************************/ private bool checkSyntaxAssemblyTextBox(TextBox textBox) { bool ok = true; for (int i = 0; i < textBox.LineCount; i++) { char[] trimChars = new char[3] { '\r', '\n', ' ' }; string str = textBox.GetLineText(i).TrimEnd(trimChars); Bit12 val = new Bit12(0); if (!_assemblerModel.assemblyToMachine(str, out val)) { errorCode("Syntax error, row " + i + ": " + "\"" + str + "\""); ok = false; } } return(ok); }
/****************************************************** * CALL: bool ok = machineToAssembly(Bit12, out string); * TASK: Returns true if conversion from machine code * to assembly code was done successfully. * NOTE: Returns false if the inputted Bit12 doesn't * contain any (or unapproved) assembly instruction. *****************************************************/ public bool machineToAssembly(Bit12 bits, out string assemblyCode) { Operations opr; if (!extractOperation(bits.value(), out opr)) { assemblyCode = ""; return(false); } assemblyCode = opr.ToString(); // Special case if (assemblyCode == "IN" || assemblyCode == "OUT" || assemblyCode == "RETURN") { return(true); } // Otherwise read the value aswell byte addr = extractVal(bits.value()); assemblyCode += " " + addr; return(true); }
/****************************************************** * CALL: bool ok = textToModel(TextBox); * TASK: Inserts the input in the textbox to the memory. *****************************************************/ private bool textToModel(TextBox textBox) { storeLabels(); if (!checkSyntaxActiveTextbox()) { return(false); } for (int i = 0; i < textBox.LineCount; i++) { char[] trimChars = new char[3] { '\r', '\n', ' ' }; string str = textBox.GetLineText(i).TrimEnd(trimChars); Bit12 bits = new Bit12(0); bool success = _assemblerModel.stringToMachine(str, out bits); Debug.Assert(success); _assemblerModel.setAddr((byte)i, bits); } return(true); }
/****************************************************** * CALL: setAddr(byte, Bit12); * TASK: Sets position "byte" in memory to value "Bit12". *****************************************************/ public void setAddr(byte idx, Bit12 val) { Debug.Assert(idx >= 0 && idx < _size); _memory[idx] = val; }
/****************************************************** * CALL: setOutput(Bit12); * TASK: Sets the _output property to the parameter Bit12. *****************************************************/ public void setOutput(Bit12 output) { _output = output; }
/****************************************************** * CALL: setInput(Bit12); * TASK: Sets input. *****************************************************/ public void setInput(Bit12 input) { _input = input; }
/****************************************************** * CALL: processCurrentAddr(); * TASK: Interprets the current address and runs the * corresponding function. *****************************************************/ public bool processCurrentAddr() { Bit12 current = _memory[_instructionPtr]; Operations opr = Operations.LOAD; byte addr = (byte)extractVal(current.value()); if (!extractOperation(current.value(), out opr)) { return(false); } _undoStack.push(new UndoStorage(_memory, _memoryStack, _instructionPtr, _workingRegister, _input, _output)); switch (opr) { case Operations.LOAD: { _workingRegister = _memory[addr]; _instructionPtr = (byte)(++_instructionPtr % _size); } break; case Operations.STORE: { _memory[addr] = _workingRegister; _instructionPtr = (byte)(++_instructionPtr % _size); } break; case Operations.ADD: { _workingRegister += _memory[addr]; _instructionPtr = (byte)(++_instructionPtr % _size); } break; case Operations.SUB: { _workingRegister -= _memory[addr]; _instructionPtr = (byte)(++_instructionPtr % _size); } break; case Operations.MUL: { _workingRegister *= _memory[addr]; _instructionPtr = (byte)(++_instructionPtr % _size); } break; case Operations.JUMP: { _instructionPtr = addr; } break; case Operations.PJUMP: { if (_workingRegister > new Bit12(0)) { _instructionPtr = addr; } else { _instructionPtr++; } } break; case Operations.IN: { _workingRegister = _input; _instructionPtr = (byte)(++_instructionPtr % _size); } break; case Operations.OUT: { _output = _workingRegister; _instructionPtr = (byte)(++_instructionPtr % _size); } break; case Operations.CALL: { _instructionPtr++; _memoryStack.push(new Bit12(_instructionPtr)); _instructionPtr = addr; } break; case Operations.RETURN: { _instructionPtr = (byte)_memoryStack.top().value(); _memoryStack.pop(); } break; } return(true); }
/****************************************************** * CALL: bool ok = assemblyToMachine(string, out Bit12); * TASK: Converts the inputted assembly string to Bit12 * machine code. *****************************************************/ public bool assemblyToMachine(string assemblyString, out Bit12 machineCode) { if (isBinary(assemblyString) && assemblyString.Length == 12) { machineCode = new Bit12(0); return(false); } string label = ""; if (containsLabel(assemblyString, out label) == LabelStatus.Success) { label = ":" + label; assemblyString = assemblyString.Replace(label, ""); if (assemblyString.Length != 0) { assemblyString = assemblyString.TrimStart(' '); } } // Empty lines to create space are fine if (assemblyString == "\r\n" || assemblyString == "\r" || assemblyString == "\n" || string.IsNullOrWhiteSpace(assemblyString)) { machineCode = new Bit12(0); return(true); } char[] trimChars = new char[3] { '\r', '\n', ' ' }; assemblyString = assemblyString.TrimEnd(trimChars); string[] splitString = assemblyString.Split(' '); // Special case where length is 1 and is a constant(number) if (splitString.Length == 1) { short val = 0; if (short.TryParse(splitString[0], out val)) { if (val < -2048 || val > 2047) { machineCode = new Bit12(0); return(false); } machineCode = new Bit12(val); return(true); } } Operations opr = Operations.LOAD; byte addr = 0; label = ""; if (splitString.Length == 2 && Enum.TryParse(splitString[0], false, out opr) && (byte.TryParse(splitString[1], out addr) || referencesLabel(assemblyString, out label)) && !(splitString[0] == "IN" || splitString[0] == "OUT" || splitString[0] == "RETURN")) { if (label.Length > 0) { addr = _labels[label]; } machineCode = new Bit12((short)opr); machineCode = new Bit12((short)(machineCode.value() << Constants.StartOprBit)); machineCode += new Bit12(addr); return(true); } if (splitString.Length == 1 && (splitString[0] == "IN" || splitString[0] == "OUT" || splitString[0] == "RETURN") && Enum.TryParse(splitString[0], false, out opr)) { machineCode = new Bit12((short)((short)opr << Constants.StartOprBit)); return(true); } machineCode = new Bit12(0); return(false); }
/****************************************************** * CALL: bool ok = SelfTest(); * TASK: Used at debugging. The method calls every (testable) * method in the class and returns true if no bug could * be found. *****************************************************/ public bool SelfTest() { bool ok = false; ok = (_size == _memory.GetLength(0)); if (!ok) { Debug.Write("SelfTest failed in GUIProjekt.AssemblerModel: size of _memory was " + _memory.GetLength(0) + ", expected " + _size + "\n"); } ok = ok && 255 == createMask(0, 7) && 63 == createMask(0, 5) && 2032 == createMask(4, 10) && 3840 == createMask(8, 11) && 4095 == createMask(0, 11) && 1020 == createMask(2, 9); System.Diagnostics.Debug.WriteLine("createMask: " + ok); Operations opr; ok = ok && extractOperation(2800, out opr) && extractOperation(256, out opr) && extractOperation(0, out opr) && extractOperation(1, out opr) && extractOperation(1337, out opr); System.Diagnostics.Debug.WriteLine("extractOperation: " + ok); short bits1 = 400; short bits2 = 255; short bits3 = 600; short bits4 = 800; short bits5 = 1028; short bits6 = 2950; ok = ok && 1 == (byte)extractValFromBits(Constants.StartOprBit, Constants.EndOprBit, bits1) && 0 == (byte)extractValFromBits(Constants.StartOprBit, Constants.EndOprBit, bits2) && 2 == (byte)extractValFromBits(Constants.StartOprBit, Constants.EndOprBit, bits3) && 3 == (byte)extractValFromBits(Constants.StartOprBit, Constants.EndOprBit, bits4) && 4 == (byte)extractValFromBits(Constants.StartOprBit, Constants.EndOprBit, bits5) && 11 == (byte)extractValFromBits(Constants.StartOprBit, Constants.EndOprBit, bits6); System.Diagnostics.Debug.WriteLine("extractValFromBits: " + ok); string labelStr = ""; ok = ok && LabelStatus.NoLabel == containsLabel("", out labelStr) && LabelStatus.NoLabel == containsLabel("MUL 420", out labelStr) && LabelStatus.SyntaxError == containsLabel(":", out labelStr) && LabelStatus.SyntaxError == containsLabel(":5", out labelStr) && LabelStatus.Blacklisted == containsLabel(":RETURN", out labelStr) && LabelStatus.Blacklisted == containsLabel(":ADD 60", out labelStr) && LabelStatus.Success == containsLabel(":HEJ 42", out labelStr) && LabelStatus.Success == containsLabel(":VARMT 255", out labelStr); System.Diagnostics.Debug.WriteLine("containsLabel: " + ok); ok = ok && isBinary("00000000") && isBinary("11111111") && isBinary("01010110") && isBinary("0") && isBinary("1"); System.Diagnostics.Debug.WriteLine("isBinary: " + ok); Bit12 machineCode = new Bit12(0); ok = ok && stringToMachine("000100010001", out machineCode) && stringToMachine("101011101110", out machineCode) && stringToMachine("011011110000", out machineCode) && stringToMachine(" ", out machineCode); System.Diagnostics.Debug.WriteLine("stringToMachine: " + ok); ok = ok && binaryStringToMachine(" ", out machineCode) && binaryStringToMachine("011111111110", out machineCode) && binaryStringToMachine("100000000001", out machineCode); System.Diagnostics.Debug.WriteLine("binaryStringToMachine: " + ok); string assemCode = ""; Bit12 val1 = new Bit12(1024); Bit12 val2 = new Bit12(2048); Bit12 val3 = new Bit12(2560); Bit12 val4 = new Bit12(1500); Bit12 val5 = new Bit12(666); Bit12 val6 = new Bit12(1); ok = ok && machineToAssembly(val1, out assemCode) && machineToAssembly(val2, out assemCode) && machineToAssembly(val3, out assemCode) && machineToAssembly(val4, out assemCode) && machineToAssembly(val5, out assemCode) && machineToAssembly(val6, out assemCode); System.Diagnostics.Debug.WriteLine("machineToAssembly: " + ok); Bit12 bit = new Bit12(0); ok = ok && assemblyToMachine(" ", out bit) && assemblyToMachine("\n", out bit) && assemblyToMachine(":VARMT 100", out bit) && assemblyToMachine("IN", out bit) && assemblyToMachine("OUT", out bit) && assemblyToMachine("PJUMP 200", out bit); System.Diagnostics.Debug.WriteLine("assemblyToMachine: " + ok); ok = ok && checkSyntaxMachine("000011111111") && checkSyntaxMachine("001101011111") && checkSyntaxMachine("100111111111") && checkSyntaxMachine("111100000000") && checkSyntaxMachine(" ") && checkSyntaxMachine("\n"); System.Diagnostics.Debug.WriteLine("checkSyntaxMachine: " + ok); return(ok); }
public static Bit12 operator /(Bit12 a, Bit12 b) { Bit12 newBit12 = new Bit12((short)(a.value() / b.value())); return(newBit12); }