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