1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Logging; 10 using Antmicro.Renode.Peripherals.Timers; 11 using Antmicro.Renode.Utilities; 12 using Antmicro.Renode.Peripherals.Bus; 13 14 namespace Antmicro.Renode.Peripherals.CPU 15 { 16 public class Andes_AndeStarV5Extension 17 { RegisterIn(IMachine machine, RiscV32 cpu)18 public static void RegisterIn(IMachine machine, RiscV32 cpu) 19 { 20 new Andes_AndeStarV5Extension().RegisterInternal(machine, cpu); 21 } 22 RegisterInternal(IMachine machine, RiscV32 cpu)23 private void RegisterInternal(IMachine machine, RiscV32 cpu) 24 { 25 this.bus = machine.SystemBus; 26 this.cpu = cpu; 27 28 cpu.RegisterCSR((ulong)CustomCSR.MachineMiscellaneousControl, () => machineMiscellaneousControlValue, value => 29 { 30 cpu.AllowUnalignedAccesses = BitHelper.IsBitSet(value, AllowUnalignedAccessesBit); 31 machineMiscellaneousControlValue = value; 32 }, "mmisc_ctl"); 33 34 // stub CSRs to make software happy 35 cpu.RegisterCSR((ulong)CustomCSR.MachineExtendedStatus, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Extended Status CSR (0x7c4) is currently not supported"); }); 36 cpu.RegisterCSR((ulong)CustomCSR.MachineCacheControl, () => 0xffffffff, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Cache Control CSR (0x7ca) is currently not supported"); }); 37 cpu.RegisterCSR((ulong)CustomCSR.InstructionCacheAndMemoryConfiguration, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfc0) is not supported"); }); 38 cpu.RegisterCSR((ulong)CustomCSR.DataCacheAndMemoryConfiguration, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfc1) is not supported"); }); 39 cpu.RegisterCSR((ulong)CustomCSR.MachineMiscellaneousConfiguration, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfc2) is not supported"); }); 40 cpu.RegisterCSR((ulong)CustomCSR.MachineMiscellaneousConfigurationRV32, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfc3) is not supported"); }); 41 cpu.RegisterCSR((ulong)CustomCSR.VectorProcessorConfiguration, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfc7) is not supported"); }); 42 cpu.RegisterCSR((ulong)CustomCSR.ClusterCacheControlBaseAddress, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfcf) is not supported"); }); 43 cpu.RegisterCSR((ulong)CustomCSR.Architecture, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfca) is not supported"); }); 44 cpu.RegisterCSR((ulong)CustomCSR.CurrentStateSaveForCrashDebugging, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfc8) is not supported"); }); 45 cpu.RegisterCSR((ulong)CustomCSR.MstatusStateSaveForCrashDebugging, () => 0x0, value => { cpu.Log(LogLevel.Warning, "Writing to the Machine Custom read-only CSR (0xfc9) is not supported"); }); 46 47 // Custom0 48 cpu.InstallCustomInstruction("iiiiiiiiiiiiiiiiii00ddddd0001011", opc => ReadFromMemoryToRegister(opc, AccessWidth.Byte, LoadExtractorByte), "LBGP"); 49 cpu.InstallCustomInstruction("iiiiiiiiiiiiiiiiii10ddddd0001011", opc => ReadFromMemoryToRegister(opc, AccessWidth.Byte, LoadExtractorByte, extendSign: false), "LBUGP"); 50 cpu.InstallCustomInstruction("iiiiiiisssssiiiiii11iiiii0001011", opc => WriteRegisterToMemory(opc, AccessWidth.Byte, StoreExtractorByte), "SBGP"); 51 cpu.InstallCustomInstruction("iiiiiiiiiiiiiiiiii01ddddd0001011", HandleADDIGP, "ADDIGP"); 52 53 // Custom1 54 cpu.InstallCustomInstruction("iiiiiiiiiiiiiiiii001ddddd0101011", opc => ReadFromMemoryToRegister(opc, AccessWidth.Word, LoadExtractorWord), "LHGP"); 55 cpu.InstallCustomInstruction("iiiiiiiiiiiiiiiii101ddddd0101011", opc => ReadFromMemoryToRegister(opc, AccessWidth.Word, LoadExtractorWord, extendSign: false), "LHUGP"); 56 cpu.InstallCustomInstruction("iiiiiiisssssiiiii100iiiii0101011", opc => WriteRegisterToMemory(opc, AccessWidth.Word, StoreExtractorWord), "SHGP"); 57 cpu.InstallCustomInstruction("iiiiiiiiiiiiiiiii010ddddd0101011", opc => ReadFromMemoryToRegister(opc, AccessWidth.DoubleWord, LoadExtractorDoubleWord), "LWGP"); 58 cpu.InstallCustomInstruction("iiiiiiisssssiiiii100iiiii0101011", opc => WriteRegisterToMemory(opc, AccessWidth.DoubleWord, StoreExtractorDoubleWord, 19), "SWGP"); 59 } 60 ReadFromMemoryToRegister(ulong opcode, AccessWidth width, Func<ulong, ulong> extractor, int immediateBits = 18, bool extendSign = true)61 private void ReadFromMemoryToRegister(ulong opcode, AccessWidth width, Func<ulong, ulong> extractor, int immediateBits = 18, bool extendSign = true) 62 { 63 var rd = (int)BitHelper.GetValue(opcode, 7, 5); 64 var imm = GetImmediate(opcode, extractor, immediateBits); 65 var memoryOffset = imm + cpu.GetRegister(MemoryOperationsImpliedRegister).RawValue; 66 67 int valueBits; 68 ulong data; 69 switch(width) 70 { 71 case AccessWidth.Byte: 72 data = bus.ReadByte(memoryOffset, cpu); 73 valueBits = 8; 74 break; 75 case AccessWidth.Word: 76 data = bus.ReadWord(memoryOffset, cpu); 77 valueBits = 16; 78 break; 79 case AccessWidth.DoubleWord: 80 data = bus.ReadDoubleWord(memoryOffset, cpu); 81 valueBits = 32; 82 break; 83 default: 84 cpu.Log(LogLevel.Error, "Invalid memory access type: {0}", width); 85 return; 86 } 87 88 if(extendSign) 89 { 90 cpu.SetRegister(rd, BitHelper.SignExtend(data, valueBits)); 91 } 92 else 93 { 94 cpu.SetRegister(rd, data); 95 } 96 } 97 WriteRegisterToMemory(ulong opcode, AccessWidth width, Func<ulong, ulong> extractor, int immediateBits = 18)98 private void WriteRegisterToMemory(ulong opcode, AccessWidth width, Func<ulong, ulong> extractor, int immediateBits = 18) 99 { 100 var rs2 = (int)BitHelper.GetValue(opcode, 20, 5); 101 var imm = GetImmediate(opcode, extractor, immediateBits); 102 var memoryOffset = imm + cpu.GetRegister(MemoryOperationsImpliedRegister).RawValue; 103 104 var regValue = cpu.GetRegister(rs2).RawValue; 105 106 switch(width) 107 { 108 case AccessWidth.Byte: 109 bus.WriteByte(memoryOffset, (byte)regValue, cpu); 110 break; 111 case AccessWidth.Word: 112 bus.WriteWord(memoryOffset, (ushort)regValue, cpu); 113 break; 114 case AccessWidth.DoubleWord: 115 bus.WriteDoubleWord(memoryOffset, (uint)regValue, cpu); 116 break; 117 default: 118 cpu.Log(LogLevel.Error, "Invalid memory access type: {0}", width); 119 break; 120 } 121 } 122 HandleADDIGP(ulong opcode)123 private void HandleADDIGP(ulong opcode) 124 { 125 var rd = (int)BitHelper.GetValue(opcode, 7, 5); 126 var imm = GetImmediate(opcode, LoadExtractorByte, 18); 127 var value = imm + cpu.GetRegister(MemoryOperationsImpliedRegister).RawValue; 128 129 cpu.SetRegister(rd, value); 130 } 131 LoadExtractorByte(ulong opcode)132 private ulong LoadExtractorByte(ulong opcode) 133 { 134 return LoadExtractorWord(opcode) | BitHelper.GetValue(opcode, 14, 1); 135 } 136 StoreExtractorByte(ulong opcode)137 private ulong StoreExtractorByte(ulong opcode) 138 { 139 return StoreExtractorWord(opcode) | BitHelper.GetValue(opcode, 14, 1); 140 } 141 LoadExtractorWord(ulong opcode)142 private ulong LoadExtractorWord(ulong opcode) 143 { 144 return BitHelper.GetValue(opcode, 21, 10) << 1 | 145 BitHelper.GetValue(opcode, 20, 1) << 11 | 146 BitHelper.GetValue(opcode, 17, 3) << 12 | 147 BitHelper.GetValue(opcode, 15, 2) << 15 | 148 BitHelper.GetValue(opcode, 31, 1) << 17; 149 } 150 StoreExtractorWord(ulong opcode)151 private ulong StoreExtractorWord(ulong opcode) 152 { 153 return StoreExtractorDoubleWord(opcode) | (BitHelper.GetValue(opcode, 8, 1) << 1); 154 } 155 StoreExtractorDoubleWord(ulong opcode)156 private ulong StoreExtractorDoubleWord(ulong opcode) 157 { 158 return BitHelper.GetValue(opcode, 9, 3) << 2 | 159 BitHelper.GetValue(opcode, 25, 6) << 5 | 160 BitHelper.GetValue(opcode, 7, 1) << 11 | 161 BitHelper.GetValue(opcode, 17, 3) << 12 | 162 BitHelper.GetValue(opcode, 15, 2) << 15 | 163 BitHelper.GetValue(opcode, 31, 1) << 17; 164 } 165 LoadExtractorDoubleWord(ulong opcode)166 private ulong LoadExtractorDoubleWord(ulong opcode) 167 { 168 return BitHelper.GetValue(opcode, 22, 9) << 2 | 169 BitHelper.GetValue(opcode, 20, 1) << 11 | 170 BitHelper.GetValue(opcode, 17, 3) << 12 | 171 BitHelper.GetValue(opcode, 15, 2) << 15 | 172 BitHelper.GetValue(opcode, 21, 1) << 17 | 173 BitHelper.GetValue(opcode, 31, 1) << 18; 174 } 175 GetImmediate(ulong opcode, Func<ulong, ulong> valueExtractor, int bitCount, bool extendSign = true)176 private ulong GetImmediate(ulong opcode, Func<ulong, ulong> valueExtractor, int bitCount, bool extendSign = true) 177 { 178 var value = valueExtractor(opcode); 179 if(extendSign) 180 { 181 return BitHelper.SignExtend(value, bitCount); 182 } 183 else 184 { 185 return value; 186 } 187 } 188 189 private ulong machineMiscellaneousControlValue; 190 191 private RiscV32 cpu; 192 private IBusController bus; 193 194 private const int AllowUnalignedAccessesBit = 6; 195 private const int MemoryOperationsImpliedRegister = 3; 196 197 private enum AccessWidth 198 { 199 Byte, 200 Word, 201 DoubleWord, 202 } 203 204 private enum CustomCSR : ulong 205 { 206 MachineCacheControl = 0x7ca, 207 MachineExtendedStatus = 0x7c4, 208 MachineMiscellaneousControl = 0x7d0, 209 InstructionCacheAndMemoryConfiguration = 0xfc0, 210 DataCacheAndMemoryConfiguration = 0xfc1, 211 MachineMiscellaneousConfiguration = 0xfc2, 212 MachineMiscellaneousConfigurationRV32 = 0xfc3, 213 VectorProcessorConfiguration = 0xfc7, 214 ClusterCacheControlBaseAddress = 0xfcf, 215 Architecture = 0xfca, 216 CurrentStateSaveForCrashDebugging = 0xfc8, 217 MstatusStateSaveForCrashDebugging = 0xfc9 218 } 219 } 220 } 221