private InstructionPayload ComposeLoad(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 2 && payload.Funct3 == CLWSP) { parser32.ParseLwSp(payload, p); } if (payload.Op == 2 && payload.Funct3 == CLDSP) { parser64.ParseLdSp(payload, p); } if (payload.Op == 0 && payload.Funct3 == CLW) { parser32.ParseLw(payload, p); } if (payload.Op == 0 && payload.Funct3 == CLD) { parser64.ParseLd(payload, p); } return(p); }
public override bool Execute(Instruction instruction, InstructionPayload payload) { var funct3 = payload.Funct3; var funct7 = payload.Funct7; var rd = payload.Rd; var rs1 = payload.Rs1; var rs1SignedValue = Register.ReadSignedLong(rs1); var rs1UnsignedValue = Register.ReadUnsignedLong(rs1); var rs2 = payload.Rs2; var rs2SignedValue = Register.ReadSignedInt(rs2); var rs2UnsignedValue = Register.ReadUnsignedInt(rs2); Logger.Info("Opcode 0C : rd = {rd}, rs1 = {rs1}, rs2 = {rs2}, funct3 = {f3}, funct7 = {f7}", rd, rs1, rs2, payload.Funct3, payload.Funct7); if (funct7 == 0x01) { HandleRV64M(payload); } else { HandleRv64I(instruction, funct3, funct7, rd, rs1, rs1SignedValue, rs1UnsignedValue, rs2SignedValue, rs2UnsignedValue); } return(true); }
public override bool Execute(Instruction instruction, InstructionPayload payload) { var rs1 = payload.Rs1; var rd = payload.Rd; var f3 = payload.Funct3; Logger.Info("Opcode 03: rd={rd}, rs1={rs1}, funct3={funct3}, Unsigned Imm = {uimm:X}", rd, rs1, f3, payload.UnsignedImmediate); /* * Bit 31 .. 28 | 27 26 25 24 23 22 21 20 * * 28..31 = FM * * Successor * 20 = SW, * 21 = SR * 22 = SO * 23 = SI * * Predecessor * 24 = PW * 25 = PR * 26 = PO * 27 = PI */ // No idea what to do right now.. return(true); }
public void OpenDebugConsole(InstructionPayload payload) { Console.WriteLine(">> Debug Console. Type h for help"); var continueDebug = true; while (continueDebug) { if (payload != null) { Console.WriteLine(">> Next " + payload.GetHumanReadbleContent() + "\n"); } Console.Write(">>"); var input = Console.ReadLine(); var toUpper = input.ToUpper(); if (toUpper.Equals("H")) { ShowDebugHelp(); } if (toUpper.Equals(command_rd)) { var registerdump = environment.GetRegisterStates(); Console.WriteLine(registerdump); } if (toUpper.Equals("C") || toUpper.Equals("N") || toUpper.Equals("Q")) { continueDebug = false; } } }
public void Execute(Instruction instruction, InstructionPayload payload) { if (!opCodeRegistry.IsInitialized) { Logger.Error("CPU is not initialized"); throw new RiscVSimException("CPU is not initialized: Please call init() first!"); } var curOpCode = instruction.OpCode; // Execute the command now var opCodeCommand = opCodeRegistry.Get(curOpCode); if (opCodeCommand == null) { string opCodeNotSupportedErrorMessage = String.Format("Implementation for OpCode {0} cannot be found", curOpCode); Logger.Error(opCodeNotSupportedErrorMessage); throw new OpCodeNotSupportedException(opCodeNotSupportedErrorMessage); } var incPc = opCodeCommand.Execute(instruction, payload); if (incPc) { register.NextInstruction(instruction.InstructionLength); } }
/* * addiw rd rs1 imm12 14..12=0 6..2=0x06 1..0=3 * slliw rd rs1 31..25=0 shamtw 14..12=1 6..2=0x06 1..0=3 * srliw rd rs1 31..25=0 shamtw 14..12=5 6..2=0x06 1..0=3 * sraiw rd rs1 31..25=32 shamtw 14..12=5 6..2=0x06 1..0=3 * */ public override bool Execute(Instruction instruction, InstructionPayload payload) { var rd = payload.Rd; var rs1 = payload.Rs1; var immediate = payload.SignedImmediate; int f3 = payload.Funct3; // The *W commands have the 32 Bit boundaries. Do the computing within these boundaries and then extend to 64 Bit. var rs1ValueSigned = Register.ReadSignedInt(rs1); var rs1ValueUnsigned = Register.ReadUnsignedInt(rs1); int signedIntResult; uint unsignedIntResult; IEnumerable <byte> result; Logger.Info("Opcode 06 : rd = {rd}, rs1 = {rs1}, immediate = {imm}, funct3 = {funct3}", rd, rs1, immediate, f3); switch (f3) { // addiw case 0: signedIntResult = rs1ValueSigned + immediate; result = GetSignedLongBytes(signedIntResult); break; // slliw case 1: var leftShiftAmount = immediate & 0x1F; // the last 5 bytes are the shift increment; unsignedIntResult = rs1ValueUnsigned << leftShiftAmount; result = GetSignedLongBytes(unsignedIntResult); break; // srliw and sraiw case 5: // https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators var rightShiftAmount = immediate & 0x1F; var rightShiftMode = (immediate & 0x0400); if (rightShiftMode == 0x400) { signedIntResult = rs1ValueSigned >> rightShiftAmount; result = GetSignedLongBytes(signedIntResult); } else { unsignedIntResult = rs1ValueUnsigned >> rightShiftAmount; result = GetSignedLongBytes(unsignedIntResult); } break; default: throw new OpCodeNotSupportedException(String.Format("OpCode = {0}, Funct3 = {1}", instruction.OpCode, f3)); } if (result != null) { Register.WriteBlock(rd, result); } return(true); }
private InstructionPayload ComposeRegister(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 1 && payload.Funct3 == 4 && payload.Funct2 == 3) { var mode = payload.Funct6 & 0x07; if (mode == 0x03) { // F4 = 8 parser32.ParseCaGeneric(payload, p); } if (mode == 0x07) { // F4 = 9 => C.SUBW / C.ADDW parser64.ParseAddWSubW(payload, p); } } if (payload.Op == 2 && payload.Funct3 == 4) { parser32.ParseAddAndMv(payload, p); } return(p); }
public override bool Execute(Instruction instruction, InstructionPayload payload) { var rs1 = payload.Rs1; var rs2 = payload.Rs2; var rd = payload.Rd; var f3 = payload.Rd; // F7 pattern var f7 = payload.Funct7; var f5 = f7 >> 2; // bits 31 ... 27 var aq = (f7 & 0x02) >> 1; // acquire bit 26 var rl = f7 & 0x01; // release bit 25 Logger.Info("OpCode 0B : rd = {rd}, rs1 = {rs1}, rs2 = {rs2}, funct3 = {f3}, aq = {aq}, rl = {rl}, f5 = {f5}", rd, rs1, rs2, f3, aq, rl, f5); // f3 = 2 => RV32I W operations // f3 = 3 => RV64I D operations if (f3 == 2) { atomic.ExecuteW(rd, rs1, rs2, rl, aq, f5); } else { string message = String.Format("Invalid coding (fe={0:X} detected for the F3 coding in the A-Extension", f3); Logger.Error(message); throw new RiscVSimException(message); } return(true); }
public override bool Execute(Instruction instruction, InstructionPayload payload) { var rd = payload.Rd; var rs1 = payload.Rs1; var signedImmediate = payload.SignedImmediate; var rs1Value = Register.ReadUnsignedInt(rs1); Logger.Info("Opcode00 : rd = {rd}, rs1 = {rs1}", rd, rs1); IEnumerable <byte> buffer; byte[] result; var memoryAddress = MathHelper.Add(rs1Value, signedImmediate); switch (payload.Funct3) { case lh: // LH loads a 16-bit value from memory, then sign-extends to 32 - bits before storing in rd. buffer = Memory.GetHalfWord(memoryAddress); result = MathHelper.PrepareLoad(buffer.ToArray(), 4, true); break; case lhu: // LHU loads a 16-bit value from memory but then zero extends to 32 - bits before storing in rd. buffer = Memory.GetHalfWord(memoryAddress); result = MathHelper.PrepareLoad(buffer.ToArray(), 4, true); break; case lb: buffer = Memory.GetByte(memoryAddress); result = MathHelper.PrepareLoad(buffer.ToArray(), 4, true); break; case lbu: buffer = Memory.GetByte(memoryAddress); result = MathHelper.PrepareLoad(buffer.ToArray(), 4, true); break; case lw: buffer = Memory.GetWord(memoryAddress); result = buffer.ToArray(); break; case lwu: buffer = Memory.GetWord(memoryAddress); result = buffer.ToArray(); break; default: throw new OpCodeNotSupportedException(String.Format("OpCode = {0}, Funct3 = {1}", instruction.OpCode, payload.Funct3)); } Register.WriteBlock(rd, result); return(true); }
public InstructionPayload BuildJType(int opcode, int rd, int imm) { var instruction = new Instruction(InstructionType.J_Type, opcode, 2); var payload = new InstructionPayload(instruction, null); payload.Rd = rd; payload.SignedImmediate = imm; return(payload); }
public InstructionPayload BuildUType(int opcode, int rd, uint uimmediate) { var instruction = new Instruction(InstructionType.U_Type, opcode, 2); var payload = new InstructionPayload(instruction, null); payload.Rd = rd; payload.UnsignedImmediate = uimmediate; return(payload); }
public InstructionPayload Compose(Instruction ins, RvcPayload payload) { InstructionPayload instructionPayload = null; // Use the Rvc32 Factory for decoding if (ins.OpCode == Store) { instructionPayload = ComposeStore(ins, payload); } // First code with the goal getting some ideas.. if (ins.OpCode == Load) { instructionPayload = ComposeLoad(ins, payload); } if (ins.OpCode == JumpAndLinkRegister) { instructionPayload = ComposeJalr(ins, payload); } if (ins.OpCode == JumpAndLink) { instructionPayload = ComposeJal(ins, payload); } if (ins.OpCode == Immediate) { instructionPayload = ComposeImmediate(ins, payload); } if (ins.OpCode == Register) { instructionPayload = ComposeRegister(ins, payload); } if (ins.OpCode == CondBrach) { instructionPayload = ComposeBranch(ins, payload); } if (ins.OpCode == Lui) { instructionPayload = ComposeLui(ins, payload); } if (ins.OpCode == System) { instructionPayload = ComposeSystem(ins, payload); } return(instructionPayload); }
private void Jump(InstructionPayload payload) { var immediate = payload.SignedImmediate; var pcIndex = Register.ProgramCounter; var pc = Register.ReadUnsignedLong(pcIndex); //var newPc = pc + immediate; var newPc = MathHelper.Add(pc, immediate); Register.WriteUnsignedLong(pcIndex, newPc); }
private InstructionPayload ComposeImmediate(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 0 && payload.Funct3 == ADDI4SPN) { parser32.ParseAddi4Spn(payload, p); } if (payload.Op == 1 && payload.Funct3 == 0) { parser32.ParseAddi(payload, p); } if (payload.Op == 1 && payload.Funct3 == 3) { parser32.ParseAddi16Sp(payload, p); } if (payload.Op == 1 && payload.Funct3 == 4) { if (payload.Funct2 == 0) { parser32.ParseSrli(payload, p); } if (payload.Funct2 == 1) { parser32.ParseSrai(payload, p); } if (payload.Funct3 == 4 && payload.Funct2 == 2) { parser32.ParseAndi(payload, p); } } if (payload.Op == 1 && payload.Funct3 == 2) { // C.LI parser32.ParseLi(payload, p); } if (payload.Op == 2 && payload.Funct3 == CSLLI) { parser32.ParseSlli(payload, p); } return(p); }
public override bool Execute(Instruction instruction, InstructionPayload payload) { var rs1 = payload.Rs1; var rd = payload.Rd; var f3 = payload.Funct3; Logger.Info("Opcode 03: rd={rd}, rs1={rs1}, funct3={funct3}, Unsigned Imm = {uimm:X}", rd, rs1, f3, payload.UnsignedImmediate); return(true); }
public InstructionPayload BuildBType(int opcode, int rs1, int rs2, int f3, int immediate) { var instruction = new Instruction(InstructionType.B_Type, opcode, 2); var payload = new InstructionPayload(instruction, null); payload.Rs1 = rs1; payload.Rs2 = rs2; payload.Funct3 = f3; payload.SignedImmediate = immediate; return(payload); }
private InstructionPayload ComposeImmediate32(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 1 && payload.Funct3 == ADDIW) { parser64.ParseAddiW(payload, p); } return(p); }
private InstructionPayload ComposeSystem(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 2 && payload.Funct3 == 4) { parser32.ParseEbreak(payload, p); } return(p); }
public void NotifyBeforeExec(InstructionPayload payload) { if (payload == null) { throw new ArgumentNullException("payload"); } if (verboseMode) { Console.WriteLine(payload.GetHumanReadbleContent()); } }
private void HandleCsr(InstructionPayload payload) { Logger.Info("CSR Call detected."); var csrIndex = payload.SignedImmediateComplete; var rs1 = payload.Rs1; var rd = payload.Rd; var rs1Value = Register.ReadSignedInt(rs1); var csrValue = ReadAndExtendCsr(csrIndex); // CSR Value is 5 Bit and gets zero extended to the register length switch (payload.Funct3) { // // Atomic Read Write CSR : An atomic Swap of CSR register content and integer register // case csrrw: DoCsrrw(rd, csrIndex, csrValue, rs1Value); break; // // Atomic Read and Set Bits in CSR // case csrrs: DoCsrrs(rd, rs1, csrIndex, csrValue, rs1Value); break; // // Atomic Read and Clear Bits in CSR // case csrrc: DoCsrrc(rd, rs1, csrIndex, csrValue, rs1Value); break; case csrrwi: DoCsrrw(rd, csrIndex, csrValue, rs1); break; case csrrsi: DoCsrrs(rd, rs1, csrIndex, csrValue, rs1); break; case csrrci: DoCsrrc(rd, rs1, csrIndex, csrValue, rs1); break; default: throw new RiscVSimException("Unknown CSR instruction detected!"); } }
public InstructionPayload BuildRType(int opcode, int rs1, int rs2, int rd, int f3, int f7) { var instruction = new Instruction(InstructionType.R_Type, opcode, 2); var payload = new InstructionPayload(instruction, null); payload.Rs1 = rs1; payload.Rs2 = rs2; payload.Rd = rd; payload.Funct3 = f3; payload.Funct7 = f7; return(payload); }
private InstructionPayload ComposeLui(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 1 && payload.Funct3 == 3) { // C.LUI parser32.ParseLui(payload, p); } return(p); }
public InstructionPayload BuildIType_Unsigned(int opcode, int rd, int f3, int rs1, uint imm) { var instruction = new Instruction(InstructionType.I_Type, opcode, 2); var payload = new InstructionPayload(instruction, null); payload.Rd = rd; payload.Funct3 = f3; payload.Rs1 = rs1; payload.UnsignedImmediate = imm; return(payload); }
public override bool Execute(Instruction instruction, InstructionPayload payload) { var rs2 = payload.Rs2; var rs1 = payload.Rs1; var rs1Value = Register.ReadUnsignedInt(rs1); // memory address = s1 + immediate var rs2Block = Register.ReadBlock(rs2); //var memoryAddress = Convert.ToUInt32(rs1Value + payload.SignedImmediate); var memoryAddress = MathHelper.Add(rs1Value, payload.SignedImmediate); var list = new List <byte>(); Logger.Info("Opcode 08 : rs1 = {rs1}, rs2 = {rs2}, immediate = {imm}", rs1, rs2, payload.SignedImmediate); switch (payload.Funct3) { case sb: // sb copies only the lowest 8 Bit list.Add(rs2Block.First()); break; case sh: // sh copies only the lowest 16 Bit list.Add(rs2Block.First()); list.Add(rs2Block.ElementAt(1)); break; case sw: // sw copies only the lowest 32 Bit list.Add(rs2Block.First()); list.Add(rs2Block.ElementAt(1)); list.Add(rs2Block.ElementAt(2)); list.Add(rs2Block.ElementAt(3)); break; case sd: list.AddRange(rs2Block); break; // Error default: throw new OpCodeNotSupportedException(String.Format("OpCode = {0}, Funct3 = {1}", instruction.OpCode, payload.Funct3)); } Memory.Write(memoryAddress, list); return(true); }
public override bool Execute(Instruction instruction, InstructionPayload payload) { /* * # RV64M * mulw rd rs1 rs2 31..25=1 14..12=0 6..2=0x0E 1..0=3 * divw rd rs1 rs2 31..25=1 14..12=4 6..2=0x0E 1..0=3 * divuw rd rs1 rs2 31..25=1 14..12=5 6..2=0x0E 1..0=3 * remw rd rs1 rs2 31..25=1 14..12=6 6..2=0x0E 1..0=3 * remuw rd rs1 rs2 31..25=1 14..12=7 6..2=0x0E 1..0=3 * */ if (payload.Funct7 != 0x01) { throw new RiscVSimException("Invalid F7 Coding for RV64M opcode detected!"); } var rd = payload.Rd; var rs1Coding = Register.ReadBlock(payload.Rs1); var rs1CodingLower = rs1Coding.Take(4); var rs2Coding = Register.ReadBlock(payload.Rs2); var rs2CodingLower = rs2Coding.Take(4); switch (payload.Funct3) { // mulw case 0: multiplier.ExecuteMulw(rd, rs1CodingLower, rs2CodingLower); break; case 4: case 5: divider.Divw(rd, rs1CodingLower, rs2CodingLower); break; case 6: case 7: divider.Remw(rd, rs1CodingLower, rs2CodingLower); break; // Error default: throw new OpCodeNotSupportedException(String.Format("OpCode = {0}, Funct3 = {1}", instruction.OpCode, payload.Funct3)); } return(true); }
private InstructionPayload ComposeJalr(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Funct3 == 4) { // C.JR (f4 = 8) // C.JALR (f4 = 9) parser32.ParseJrAndJalr(payload, p); } return(p); }
private void HandleRV64M(InstructionPayload payload) { Logger.Info("Multiplier extension detected"); switch (payload.Funct3) { // mul case 0: multiplier.ExecuteMul(payload.Rd, Register.ReadBlock(payload.Rs1), Register.ReadBlock(payload.Rs2)); break; // mulh case 1: // See Mlhu // mulhsu case 2: // See Mlhu // mulhu case 3: multiplier.ExecuteMulh(payload.Rd, Register.ReadBlock(payload.Rs1), Register.ReadBlock(payload.Rs2)); break; // div case 4: // see divu // divu case 5: divider.Div(payload.Rd, Register.ReadBlock(payload.Rs1), Register.ReadBlock(payload.Rs2)); break; // rem case 6: // see remu // remu case 7: divider.Rem(payload.Rd, Register.ReadBlock(payload.Rs1), Register.ReadBlock(payload.Rs2)); break; // Error default: throw new OpCodeNotSupportedException(String.Format("OpCode = {0}, Funct3 = {1}", payload.OpCode, payload.Funct3)); } }
private InstructionPayload ComposeRegister(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 1 && payload.Funct3 == 4 && payload.Funct2 == 3) { parser32.ParseCaGeneric(payload, p); } if (payload.Op == 2 && payload.Funct3 == 4) { parser32.ParseAddAndMv(payload, p); } return(p); }
private InstructionPayload ComposeBranch(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Funct3 == BEQZ) { parser32.ParseBeqzAndBnez(payload, p, true); } if (payload.Funct3 == BNEZ) { parser32.ParseBeqzAndBnez(payload, p, false); } return(p); }
private InstructionPayload ComposeStore(Instruction ins, RvcPayload payload) { // Set the opcode, type and coding InstructionPayload p = new InstructionPayload(ins, payload.Coding); if (payload.Op == 0 && payload.Funct3 == CSW) { parser32.ParseSw(payload, p); } if (payload.Op == 2 && payload.Funct3 == CSWSP) { parser32.ParseSwSp(payload, p); } return(p); }