public static void ExeLoadInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { res.Register[registersOpcode[args[0]]].Value = Healper.CalculatLoadComand((uint)res.Register[registersOpcode[args[1]]].Value, uint.Parse(args[2]), exeCommand, res.Memory); }
public static void ExeStoreInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { var registerValue = res.Register[registersOpcode[args[0]]].Value; switch (exeCommand) { case "sb": res.Memory[(uint)(res.Register[registersOpcode[args[1]]].Value + Int32.Parse(args[2]))] = (byte)(registerValue & Convert.ToInt32("11111111", 2)); break; case "sh": res.Memory[(uint)(res.Register[registersOpcode[args[1]]].Value + Int32.Parse(args[2]))] = (byte)(registerValue & Convert.ToInt32("11111111", 2)); res.Memory[(uint)(res.Register[registersOpcode[args[1]]].Value + Int32.Parse(args[2]) + 1)] = (byte)((registerValue >> 8) & Convert.ToInt32("11111111", 2)); break; default: res.Memory[(uint)(res.Register[registersOpcode[args[1]]].Value + Int32.Parse(args[2]))] = (byte)(registerValue & Convert.ToInt32("11111111", 2)); res.Memory[(uint)(res.Register[registersOpcode[args[1]]].Value + Int32.Parse(args[2]) + 1)] = (byte)((registerValue >> 8) & Convert.ToInt32("11111111", 2)); res.Memory[(uint)(res.Register[registersOpcode[args[1]]].Value + Int32.Parse(args[2]) + 2)] = (byte)((registerValue >> 16) & Convert.ToInt32("11111111", 2)); res.Memory[(uint)(res.Register[registersOpcode[args[1]]].Value + Int32.Parse(args[2]) + 3)] = (byte)(registerValue >> 24); break; } }
public static void ExeRInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { if (registersOpcode[args[0]] != 0) { res.Register[registersOpcode[args[0]]].Value = Healper.CalculatRComand( res.Register[registersOpcode[args[1]]].Value, res.Register[registersOpcode[args[2]]].Value, exeCommand); } }
public static void ExeUInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { switch (exeCommand) { case "auipc": res.Register[registersOpcode[args[0]]].Value = res.Register[registersOpcode["pc"]].Value + (Int32.Parse(args[1]) << 12); break; case "lui": res.Register[registersOpcode[args[0]]].Value = Int32.Parse(args[1]) << 12; break; } }
public static void ExeJInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { switch (exeCommand) { case "jal": res.Register[registersOpcode[args[0]]].Value = res.Register[registersOpcode["pc"]].Value + 4; res.Register[registersOpcode["pc"]].Value += Int32.Parse(args[1]) & Convert.ToInt32("11111111111111111111", 2); break; case "j": res.Register[registersOpcode["pc"]].Value += Int32.Parse(args[0]) & Convert.ToInt32("11111111111111111111", 2); break; } }
public static uint GetAddress(RiscVProgramResult res, MemorySection memorySection) { switch (memorySection) { case MemorySection.Text: return(0x10000 + res.StackTextFreePosition); case MemorySection.Static: return((uint)0x10000000 + res.StackStaticDataFreePosition); default: throw new SimulatorException { ErrorMessage = $"'{memorySection}' cannot find fit section to return from f. GetAddress" }; } }
public static void ExeIInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { if (exeCommand == "jalr") { res.Register[registersOpcode[args[0]]].Value = res.Register[registersOpcode["pc"]].Value; res.Register[registersOpcode["pc"]].Value = res.Register[registersOpcode[args[1]]].Value + Convert.ToInt32(args[1]); } else { if (registersOpcode[args[0]] != 0) { res.Register[registersOpcode[args[0]]].Value = Healper.CalculatIComand(res.Register[registersOpcode[args[1]]].Value, int.Parse(args[2]) & 4095, exeCommand); } } }
private void PutIntoAddress(RiscVProgramResult res, MemorySection memorySection, byte longByte) { switch (memorySection) { case MemorySection.Text: res.Memory.Add(0x10000 + res.StackTextFreePosition, longByte); res.StackTextFreePosition++; break; case MemorySection.Static: res.Memory.Add((uint)0x10000000 + res.StackStaticDataFreePosition, longByte); res.StackStaticDataFreePosition++; break; default: throw new SimulatorException { ErrorMessage = $"'{memorySection}' cannot find fit section to return from f. GetAddress" }; } }
public static void ExeEInstruction(RiscVProgramResult res, string exeCommand, List <string> args, ref bool endProgram, Dictionary <string, uint> stringTable) { switch (exeCommand) { case "ebreak": endProgram = true; break; case "ecall": switch (res.Register[10].Value) { case 1: if (res.Register[11].Value < 0) { throw new SimulatorException { ErrorMessage = $"ecall code 1 cannot get negative number as argument{res.Register[11].Value} " } } ; res.StackDynamicDataFreePosition += (uint)res.Register[11].Value; break; case 2: res.Register[12].Value = new Random().Next(0, res.Register[11].Value); break; case 3: res.alphanumericData.Output = new List <string>(); break; case 4: if (res.Register[11].Value < 0 || res.Register[11].Value > 32) { throw new SimulatorException { ErrorMessage = $"ecall code 4 can only get numbers 0~32 at register a1" } } ; res.alphanumericData.Output.Add( $"The number in register '{res.Register[res.Register[11].Value].Name}' : {res.Register[res.Register[11].Value].Value}"); break; case 5: res.alphanumericData.Output.Add( $"The ASCI code in register '{res.Register[res.Register[11].Value].Name}' is {Convert.ToChar(res.Register[res.Register[11].Value].Value)}"); break; case 6: res.alphanumericData.Output.Add( $"The string locate at address '{res.Register[11].Value}' is {GetString(res.Register[11].Value, res.Memory)}"); break; case 7: if (string.IsNullOrEmpty(res.alphanumericData.Input)) { res.alphanumericData.Output.Add($"Please Enter Your 'string' you want to search"); res.alphanumericData.Line = res.Register[10].Value; endProgram = true; break; } res.alphanumericData.Output.Add(GetStringAddressMemory(res.alphanumericData.Input, stringTable)); res.alphanumericData.Line = -1; res.alphanumericData.Input = ""; break; case 8: if (string.IsNullOrEmpty(res.alphanumericData.Input)) { res.alphanumericData.Output.Add($"Please enter a number to store"); res.alphanumericData.Line = res.Register[10].Value; endProgram = true; break; } res.Register[11].Value = int.Parse(res.alphanumericData.Input); break; case 9: res.Register[11].Value = res.alphanumericData.LastChar; break; case 10: res.GraphicBorder.Add(CreatePoint(res.Register[11].Value, res.Register[12].Value, res.Register[13].Value)); break; case 11: res.Register[13].Value = GetColor(res.Register[11].Value, res.Register[12].Value, res.GraphicBorder); break; case 12: for (int i = 0; i < 21; i++) { for (int j = 0; j < 21; j++) { res.GraphicBorder.Add(CreatePoint(i, j, res.Register[11].Value)); } } break; case 13: for (int j = 0; j < 20; j++) { res.GraphicBorder.Add(CreatePoint(4, j, res.Register[11].Value)); } break; case 14: res.GraphicBorder.Add(CreatePoint(2, 10, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(3, 9, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(3, 11, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(4, 8, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(4, 12, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(5, 7, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(5, 13, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(6, 7, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(6, 13, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(7, 8, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(7, 12, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(8, 9, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(8, 11, res.Register[11].Value)); res.GraphicBorder.Add(CreatePoint(9, 10, res.Register[11].Value)); break; default: throw new SimulatorException { ErrorMessage = $"bad ecall argument '{res.Register[10].Value}' " }; } break; } }
public static void ExeShamtIInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { res.Register[registersOpcode[args[0]]].Value = Healper.CalculatIComand(res.Register[registersOpcode[args[1]]].Value, int.Parse(args[2]) & 31, exeCommand); }
public static void ExeBInstruction(RiscVProgramResult res, string exeCommand, List <string> args) { if (int.TryParse(args[2], out int number)) { switch (exeCommand) { case "beq": if (res.Register[registersOpcode[args[0]]].Value == res.Register[registersOpcode[args[1]]].Value) { res.Register[registersOpcode["pc"]].Value += number; } break; case "bne": if (res.Register[registersOpcode[args[0]]].Value != res.Register[registersOpcode[args[1]]].Value) { res.Register[registersOpcode["pc"]].Value += number; } break; case "blt": if (res.Register[registersOpcode[args[0]]].Value <= res.Register[registersOpcode[args[1]]].Value) { res.Register[registersOpcode["pc"]].Value += number; } break; case "bge": if (res.Register[registersOpcode[args[0]]].Value > res.Register[registersOpcode[args[1]]].Value) { res.Register[registersOpcode["pc"]].Value += number; } break; case "bltu": if (Convert.ToUInt32(res.Register[registersOpcode[args[0]]].Value) < Convert.ToUInt32(res.Register[registersOpcode[args[1]]].Value)) { res.Register[registersOpcode["pc"]].Value += number; } break; case "bgeu": if (Convert.ToUInt32(res.Register[registersOpcode[args[0]]].Value) >= Convert.ToUInt32(res.Register[registersOpcode[args[1]]].Value)) { res.Register[registersOpcode["pc"]].Value += number; } break; } } else { throw new SimulatorException { ErrorMessage = $"unknown offset in B" }; } }
private void DoSecondParse(RiscVProgramResult res, List <RiscVProgramResult> debugRes, bool DebugMode, Dictionary <uint, UncompleteParseData> uncompleteParse, Dictionary <string, Lable> labelTable, Dictionary <uint, ExeCommand> commandsToExe) { int commandToFix = 0; bool lowLabelCommand = false; foreach (var commandToUpdate in uncompleteParse) { try { for (int j = 0; j < 4; j++) //read command from memory, each command (32b) needs 4 bytes { commandToFix |= res.Memory[(uint)(commandToUpdate.Key + j)] << 8 * j; } lowLabelCommand = Healper.IsLowLabelCommand(commandToUpdate.Value.optionalLabel, out var label); if (!labelTable.ContainsKey(label)) { throw new SimulatorException { ErrorMessage = $"cannot find label {label}" } } ; switch (commandToUpdate.Value.command) { case "addi": case "slti": case "sltiu": case "xori": case "ori": case "andi": case "jalr": if (lowLabelCommand) { commandsToExe[commandToUpdate.Key].Args[2] = (labelTable[label].Address & Convert.ToInt32("111111111111", 2)).ToString(); commandToFix |= ((int)labelTable[label].Address & Convert.ToInt32("111111111111", 2)) << 20; } else { // we cant fit 20 high bit to imm 12 bit so we cut the bits from 12-19 (the high bits) and move them to the left(20-31) to fit the imm 12 bits labelTable[label].Address &= 16773120; //CUT commandToFix |= (int)labelTable[label].Address << 8; //MOVE + MERGE commandsToExe[commandToUpdate.Key].Args[2] = ((labelTable[label].Address & Convert.ToInt32("00000000111111111111000000000000", 2)) >> 12).ToString(); } break; case "lui": if (lowLabelCommand) { commandsToExe[commandToUpdate.Key].Args[1] = (labelTable[label].Address & Convert.ToInt32("111111111111", 2)).ToString(); commandToFix |= ((int)labelTable[label].Address & Convert.ToInt32("111111111111", 2)) << 12; } else { commandsToExe[commandToUpdate.Key].Args[1] = (UInt32.Parse(labelTable[label].Address.ToString()) >> 12).ToString(); commandToFix |= (int)labelTable[label].Address & Convert.ToInt32("11111111111111111111000000000000", 2); } break; case "auipc": if (lowLabelCommand) { commandsToExe[commandToUpdate.Key].Args[1] = ((int)labelTable[label].Address & Convert.ToInt32("111111111111", 2)).ToString(); commandToFix |= ((int)labelTable[label].Address & Convert.ToInt32("111111111111", 2)) << 12; } else { //commandsToExe[commandToUpdate.Key].Args[1] = (labelTable[label].Address & Convert.ToInt32("11111111111111111111000000000000", 2)).ToString(); commandsToExe[commandToUpdate.Key].Args[1] = (UInt32.Parse(labelTable[label].Address.ToString()) >> 12).ToString(); commandToFix |= (int)labelTable[label].Address & Convert.ToInt32("11111111111111111111000000000000", 2); } break; } var longBytes = BitConverter.GetBytes(commandToFix); //Enter Command to Stack if (DebugMode) { foreach (var snapshotMemory in debugRes) { if (debugRes.IndexOf((snapshotMemory)) >= commandToUpdate.Value.lineNumber) { for (int j = 0; j < 4; j++) { snapshotMemory.Memory[(uint)(commandToUpdate.Key + j)] = longBytes[j]; } } } } else { for (int j = 0; j < 4; j++) { res.Memory[(uint)(commandToUpdate.Key + j)] = longBytes[j]; } } } catch (SimulatorException e) { throw new ErrorInResult { Line = commandToUpdate.Value.lineNumber, Message = e.ErrorMessage }; } catch (Exception e) { throw new ErrorInResult { Line = commandToUpdate.Value.lineNumber, Message = "Internal Error" }; } } }
public async Task <ActionResult> ProgramToRun([FromBody] RiscVProgram req) { var cursor = 0; var commandInBinarryFormat = 0; var memorySection = MemorySection.Text; Dictionary <string, Lable> labelTable = new Dictionary <string, Lable>(); Dictionary <uint, UncompleteParseData> uncompleteParse = new Dictionary <uint, UncompleteParseData>(); Dictionary <uint, ExeCommand> commandsToExe = new Dictionary <uint, ExeCommand>(); RiscVProgramResult res = new RiscVProgramResult(req); List <RiscVProgramResult> debugRes = new List <RiscVProgramResult>(); Dictionary <string, uint> stringTable = new Dictionary <string, uint>();//only for ecall 7 use var TextArray = req.Program.Split('\n').Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); var programTextArray = new string[TextArray.Length][]; for (int i = 0; i < TextArray.Length; i++) { programTextArray[i] = TextArray[i].Split('#').FirstOrDefault()?.Split(' ', '\t', '\r').Where(s => !string.IsNullOrWhiteSpace(s)) .ToArray(); /* programTextArray[i] = TextArray[i].Split(' ', '\t', '\r').Where(s => !string.IsNullOrWhiteSpace(s)) * .ToArray(); * if (programTextArray[i].FirstOrDefault(x => x.StartsWith('#')) != null) * { * var index = programTextArray[i].IndexOf(programTextArray[i].FirstOrDefault(x => x.StartsWith('#'))); * programTextArray[i] = programTextArray[i].Take(index).ToArray(); * }*/ } bool newLabel = false; for (int i = 0; i < programTextArray.Length; i++) { for (int j = 0; j < programTextArray[i].Length; j++) { try { if (Healper.IsLabel(programTextArray, ref i, ref j, out var label)) { if (!labelTable.TryAdd(label, null)) { return(BadRequest(new ErrorInResult { Line = i, Message = $"The label {label} already exist." })); } newLabel = true; } if (programTextArray[i][j][0] == '.') { var directive = Healper.GetDirective(programTextArray, ref i, ref j); if (DirectiveNumber.ContainsKey(directive)) { if (newLabel) { labelTable[labelTable.Keys.Last()] = new Lable { Address = Healper.GetAddress(res, memorySection), i = i, j = j }; newLabel = false; } if (programTextArray[i].Length > ++j == false) { if (programTextArray.Length > ++i == false) { throw new SimulatorException { ErrorMessage = $"'incomplete command" } } ; j = 0; } if (directive == "string") { var items = Healper.PrepareString(programTextArray, ref i, ref j); stringTable.Add(items.Substring(0, items.Length - 1), Healper.GetAddress(res, memorySection)); foreach (var item in items) { var longBytes = BitConverter.GetBytes(item); for (int z = 0; z < DirectiveNumber[directive]; z++) { PutIntoAddress(res, memorySection, longBytes.Length > z ? longBytes[z] : (byte)0); //we fill the memory with space if the number is not big enough to fit the DirectiveNumber } } } else { var items = Healper.GetListOfNumber(programTextArray, ref i, ref j); foreach (var item in items) { var longBytes = BitConverter.GetBytes(item); for (int z = 0; z < DirectiveNumber[directive]; z++) { PutIntoAddress(res, memorySection, longBytes.Length > z ? longBytes[z] : (byte)0); //we fill the memory with space if the number is not big enough to fit the DirectiveNumber } } } } else { switch (directive) { case "data": memorySection = MemorySection.Static; break; case "text": memorySection = MemorySection.Text; break; default: throw new SimulatorException { ErrorMessage = $"'{directive}' is unknown directive" }; } } } else { commandsToExe.Add(GetIntoAddress(res, memorySection), null); commandInBinarryFormat = ParseCommandWithNoImm(programTextArray, ref i, ref j, commandsToExe); if (commandInBinarryFormat == 0) { commandInBinarryFormat = ParseCommandWithImm(out string optionalLabel, out string command, programTextArray, ref i, ref j, commandsToExe); if (optionalLabel != null) { uncompleteParse.Add(Healper.GetAddress(res, memorySection), new UncompleteParseData(optionalLabel, command, i)); } } if (newLabel) { labelTable[label] = new Lable { Address = Healper.GetAddress(res, memorySection) }; newLabel = false; } var longBytes = BitConverter.GetBytes(commandInBinarryFormat); //Enter Command to Stack for (int z = 0; z < 4; z++) { PutIntoAddress(res, memorySection, longBytes[z]); } } } catch (SimulatorException e) { return(BadRequest(new ErrorInResult { Line = i, Message = e.ErrorMessage })); } catch (Exception e) { return(BadRequest(new ErrorInResult { Line = i, Message = "Internal Error" })); } } } try { DoSecondParse(res, debugRes, req.DebugMode, uncompleteParse, labelTable, commandsToExe); res.Register[32].Value = (int)commandsToExe.FirstOrDefault().Key; ExeProgram(res, debugRes, commandsToExe, req.DebugMode, stringTable); } catch (ErrorInResult e) { return(BadRequest(new ErrorInResult { Line = e.Line, Message = e.Message })); } catch (Exception e) { return(BadRequest(new ErrorInResult { Message = "Internal Error" })); } if (res.alphanumericData.Line == -1) { if (req.DebugMode) { return(Ok(debugRes)); } else { return(Ok(res)); } } return(Ok(new ContinueProgramResult { res = res, commandsToExe = commandsToExe, debugRes = debugRes, DebugMode = req.DebugMode, stringTable = stringTable })); }
private void ExeProgram(RiscVProgramResult res, List <RiscVProgramResult> debugRes, Dictionary <uint, ExeCommand> commandsToExe, bool DebugMode, Dictionary <string, uint> stringTable) { var line = 0; string command = string.Empty; List <string> args = new List <string>(); if (commandsToExe.Count == 0) { return; } bool finishExe = false; try { while (finishExe == false) { command = commandsToExe[(uint)res.Register[32].Value].Instraction; line = commandsToExe[(uint)res.Register[32].Value].Line; args = commandsToExe[(uint)res.Register[32].Value].Args; switch (command) { case "add": case "sub": case "sll": case "slt": case "sltu": case "xor": case "srl": case "sra": case "or": case "and": Instructions.ExeRInstruction(res, command, args); break; case "srai": case "slli": case "srli": Instructions.ExeShamtIInstruction(res, command, args); break; case "addi": case "slti": case "sltiu": case "xori": case "ori": case "andi": case "jalr": Instructions.ExeIInstruction(res, command, args); break; case "lb": case "lh": case "lw": case "lbu": case "lhu": Instructions.ExeLoadInstruction(res, command, args); break; case "sb": case "sh": case "sw": Instructions.ExeStoreInstruction(res, command, args); break; case "beq": case "bne": case "blt": case "bge": case "bltu": case "bgeu": Instructions.ExeBInstruction(res, command, args); break; case "lui": case "auipc": Instructions.ExeUInstruction(res, command, args); break; case "jal": case "j": Instructions.ExeJInstruction(res, command, args); break; case "ecall": case "ebreak": Instructions.ExeEInstruction(res, command, args, ref finishExe, stringTable); break; default: throw new SimulatorException { ErrorMessage = $"'unknown '{command}' command" }; } res.Register[32].Value += 4; if (commandsToExe.ContainsKey((uint)res.Register[32].Value) == false) { debugRes.Add(new RiscVProgramResult(res, line)); finishExe = true; } else { if (DebugMode) { debugRes.Add(new RiscVProgramResult(res, line)); } } } } catch (SimulatorException e) { throw new ErrorInResult { Line = line, Message = e.ErrorMessage }; } catch (Exception e) { throw new ErrorInResult { Line = line, Message = "Internal Error" }; } }