1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System; 9 using System.Collections.Generic; 10 using System.Linq; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Core.Structure; 14 using Antmicro.Renode.Utilities; 15 using Antmicro.Renode.Peripherals.CPU; 16 using Antmicro.Renode.Peripherals.Memory; 17 using ELFSharp.ELF; 18 19 using Range = Antmicro.Renode.Core.Range; 20 21 namespace Antmicro.Renode.Peripherals.Bus 22 { 23 public interface IBusController: IPeripheralContainer<IBusPeripheral, BusRangeRegistration>, IPeripheralRegister<IKnownSize, BusPointRegistration>, 24 IPeripheralRegister<ICPU, CPURegistrationPoint>, IPeripheralRegister<IBusPeripheral, BusMultiRegistration>, IPeripheralRegister<IPeripheral, NullRegistrationPoint>, 25 IPeripheralRegister<IBusPeripheral, BusParametrizedRegistration>, ICanLoadFiles, IPeripheral, IMultibyteWritePeripheral 26 { ReadByte(ulong address, IPeripheral context = null, ulong? cpuState = null)27 byte ReadByte(ulong address, IPeripheral context = null, ulong? cpuState = null); ReadByteWithState(ulong address, IPeripheral context, IContextState stateObj)28 byte ReadByteWithState(ulong address, IPeripheral context, IContextState stateObj); WriteByte(ulong address, byte value, IPeripheral context = null, ulong? cpuState = null)29 void WriteByte(ulong address, byte value, IPeripheral context = null, ulong? cpuState = null); WriteByteWithState(ulong address, byte value, IPeripheral context, IContextState stateObj)30 void WriteByteWithState(ulong address, byte value, IPeripheral context, IContextState stateObj); 31 ReadWord(ulong address, IPeripheral context = null, ulong? cpuState = null)32 ushort ReadWord(ulong address, IPeripheral context = null, ulong? cpuState = null); ReadWordWithState(ulong address, IPeripheral context, IContextState stateObj)33 ushort ReadWordWithState(ulong address, IPeripheral context, IContextState stateObj); WriteWord(ulong address, ushort value, IPeripheral context = null, ulong? cpuState = null)34 void WriteWord(ulong address, ushort value, IPeripheral context = null, ulong? cpuState = null); WriteWordWithState(ulong address, ushort value, IPeripheral context, IContextState stateObj)35 void WriteWordWithState(ulong address, ushort value, IPeripheral context, IContextState stateObj); 36 ReadDoubleWord(ulong address, IPeripheral context = null, ulong? cpuState = null)37 uint ReadDoubleWord(ulong address, IPeripheral context = null, ulong? cpuState = null); ReadDoubleWordWithState(ulong address, IPeripheral context, IContextState stateObj)38 uint ReadDoubleWordWithState(ulong address, IPeripheral context, IContextState stateObj); WriteDoubleWord(ulong address, uint value, IPeripheral context = null, ulong? cpuState = null)39 void WriteDoubleWord(ulong address, uint value, IPeripheral context = null, ulong? cpuState = null); WriteDoubleWordWithState(ulong address, uint value, IPeripheral context, IContextState stateObj)40 void WriteDoubleWordWithState(ulong address, uint value, IPeripheral context, IContextState stateObj); 41 ReadQuadWord(ulong address, IPeripheral context = null, ulong? cpuState = null)42 ulong ReadQuadWord(ulong address, IPeripheral context = null, ulong? cpuState = null); ReadQuadWordWithState(ulong address, IPeripheral context, IContextState stateObj)43 ulong ReadQuadWordWithState(ulong address, IPeripheral context, IContextState stateObj); WriteQuadWord(ulong address, ulong value, IPeripheral context = null, ulong? cpuState = null)44 void WriteQuadWord(ulong address, ulong value, IPeripheral context = null, ulong? cpuState = null); WriteQuadWordWithState(ulong address, ulong value, IPeripheral context, IContextState stateObj)45 void WriteQuadWordWithState(ulong address, ulong value, IPeripheral context, IContextState stateObj); 46 ReadBytes(ulong address, int count, byte[] destination, int startIndex, bool onlyMemory = false, IPeripheral context = null)47 void ReadBytes(ulong address, int count, byte[] destination, int startIndex, bool onlyMemory = false, IPeripheral context = null); ReadBytes(ulong address, int count, bool onlyMemory = false, IPeripheral context = null)48 byte[] ReadBytes(ulong address, int count, bool onlyMemory = false, IPeripheral context = null); 49 WriteBytes(byte[] bytes, ulong address, bool onlyMemory = false, IPeripheral context = null)50 void WriteBytes(byte[] bytes, ulong address, bool onlyMemory = false, IPeripheral context = null); WriteBytes(byte[] bytes, ulong address, int startingIndex, long count, bool onlyMemory = false, IPeripheral context = null)51 void WriteBytes(byte[] bytes, ulong address, int startingIndex, long count, bool onlyMemory = false, IPeripheral context = null); WriteBytes(byte[] bytes, ulong address, long count, bool onlyMemory = false, IPeripheral context = null)52 void WriteBytes(byte[] bytes, ulong address, long count, bool onlyMemory = false, IPeripheral context = null); 53 ZeroRange(Range range, IPeripheral context = null)54 void ZeroRange(Range range, IPeripheral context = null); TryConvertStateToUlongForContext(IPeripheral context, IContextState stateObj, out ulong? state)55 bool TryConvertStateToUlongForContext(IPeripheral context, IContextState stateObj, out ulong? state); 56 WhatIsAt(ulong address, IPeripheral context = null)57 IBusRegistered<IBusPeripheral> WhatIsAt(ulong address, IPeripheral context = null); WhatPeripheralIsAt(ulong address, IPeripheral context = null)58 IPeripheral WhatPeripheralIsAt(ulong address, IPeripheral context = null); 59 IsAddressRangeLocked(Range range, IPeripheral context = null)60 bool IsAddressRangeLocked(Range range, IPeripheral context = null); SetAddressRangeLocked(Range range, bool locked, IPeripheral context = null)61 void SetAddressRangeLocked(Range range, bool locked, IPeripheral context = null); 62 SetPeripheralEnabled(IPeripheral peripheral, bool value)63 void SetPeripheralEnabled(IPeripheral peripheral, bool value); IsPeripheralEnabled(IPeripheral peripheral)64 bool IsPeripheralEnabled(IPeripheral peripheral); 65 GetCPUs()66 IEnumerable<ICPU> GetCPUs(); GetCPUSlot(ICPU cpu)67 int GetCPUSlot(ICPU cpu); GetCurrentCPU()68 ICPU GetCurrentCPU(); GetAllContextKeys()69 IEnumerable<IPeripheral> GetAllContextKeys(); GetRegisteredPeripherals(IPeripheral context = null)70 IEnumerable<IBusRegistered<IBusPeripheral>> GetRegisteredPeripherals(IPeripheral context = null); GetRegistrationsForPeripheralType(IPeripheral context = null)71 IEnumerable<IBusRegistered<IBusPeripheral>> GetRegistrationsForPeripheralType<T>(IPeripheral context = null); TryGetCurrentCPU(out ICPU cpu)72 bool TryGetCurrentCPU(out ICPU cpu); TryGetCurrentContextState(out IPeripheralWithTransactionState context, out T stateObj)73 bool TryGetCurrentContextState<T>(out IPeripheralWithTransactionState context, out T stateObj); 74 UnregisterFromAddress(ulong address, ICPU context = null)75 void UnregisterFromAddress(ulong address, ICPU context = null); MoveRegistrationWithinContext(IBusPeripheral peripheral, BusRangeRegistration newRegistration, ICPU context, Func<IEnumerable<IBusRegistered<IBusPeripheral>>, IBusRegistered<IBusPeripheral>> selector = null)76 void MoveRegistrationWithinContext(IBusPeripheral peripheral, BusRangeRegistration newRegistration, ICPU context, Func<IEnumerable<IBusRegistered<IBusPeripheral>>, IBusRegistered<IBusPeripheral>> selector = null); 77 AddWatchpointHook(ulong address, SysbusAccessWidth width, Access access, BusHookDelegate hook)78 void AddWatchpointHook(ulong address, SysbusAccessWidth width, Access access, BusHookDelegate hook); RemoveWatchpointHook(ulong address, BusHookDelegate hook)79 void RemoveWatchpointHook(ulong address, BusHookDelegate hook); TryGetWatchpointsAt(ulong address, Access access, out List<BusHookHandler> result)80 bool TryGetWatchpointsAt(ulong address, Access access, out List<BusHookHandler> result); RemoveAllWatchpointHooks(ulong address)81 void RemoveAllWatchpointHooks(ulong address); 82 SetHookAfterPeripheralRead(IBusPeripheral peripheral, Func<T, long, T> hook, Range? subrange = null)83 void SetHookAfterPeripheralRead<T>(IBusPeripheral peripheral, Func<T, long, T> hook, Range? subrange = null); SetHookBeforePeripheralWrite(IBusPeripheral peripheral, Func<T, long, T> hook, Range? subrange = null)84 void SetHookBeforePeripheralWrite<T>(IBusPeripheral peripheral, Func<T, long, T> hook, Range? subrange = null); ClearHookAfterPeripheralRead(IBusPeripheral peripheral)85 void ClearHookAfterPeripheralRead<T>(IBusPeripheral peripheral); 86 FindSymbolAt(ulong offset, ICPU context = null)87 string FindSymbolAt(ulong offset, ICPU context = null); 88 TryGetAllSymbolAddresses(string symbolName, out IEnumerable<ulong> symbolAddresses, ICPU context = null)89 bool TryGetAllSymbolAddresses(string symbolName, out IEnumerable<ulong> symbolAddresses, ICPU context = null); TryFindSymbolAt(ulong offset, out string name, out Symbol symbol, ICPU context = null)90 bool TryFindSymbolAt(ulong offset, out string name, out Symbol symbol, ICPU context = null); DecorateWithCPUNameAndPC(string str)91 string DecorateWithCPUNameAndPC(string str); 92 MapMemory(IMappedSegment segment, IBusPeripheral owner, bool relative = true, ICPUWithMappedMemory context = null)93 void MapMemory(IMappedSegment segment, IBusPeripheral owner, bool relative = true, ICPUWithMappedMemory context = null); FindMemory(ulong address, ICPU context = null)94 IBusRegistered<MappedMemory> FindMemory(ulong address, ICPU context = null); IsMemory(ulong address, ICPU context = null)95 bool IsMemory(ulong address, ICPU context = null); 96 Tag(Range range, string tag, ulong defaultValue = 0, bool pausing = false)97 void Tag(Range range, string tag, ulong defaultValue = 0, bool pausing = false); 98 ApplySVD(string path)99 void ApplySVD(string path); 100 LoadSymbolsFrom(IELF elf, bool useVirtualAddress = false, ulong? textAddress = null, ICPU context = null)101 void LoadSymbolsFrom(IELF elf, bool useVirtualAddress = false, ulong? textAddress = null, ICPU context = null); LoadUImage(ReadFilePath fileName, IInitableCPU cpu = null)102 void LoadUImage(ReadFilePath fileName, IInitableCPU cpu = null); 103 GetLookup(ICPU context = null)104 SymbolLookup GetLookup(ICPU context = null); 105 EnableAllTranslations(bool enable = true)106 void EnableAllTranslations(bool enable = true); EnableAllTranslations(IBusPeripheral busPeripheral, bool enable = true)107 void EnableAllTranslations(IBusPeripheral busPeripheral, bool enable = true); 108 109 IMachine Machine { get; } 110 111 bool IsMultiCore { get; } 112 113 Endianess Endianess { get; } 114 115 event Action<IMachine> OnSymbolsChanged; 116 } 117 118 public static class BusControllerExtensions 119 { EnablePeripheral(this IBusController bus, IPeripheral peripheral)120 public static void EnablePeripheral(this IBusController bus, IPeripheral peripheral) 121 { 122 bus.SetPeripheralEnabled(peripheral, true); 123 } 124 DisablePeripheral(this IBusController bus, IPeripheral peripheral)125 public static void DisablePeripheral(this IBusController bus, IPeripheral peripheral) 126 { 127 bus.SetPeripheralEnabled(peripheral, false); 128 } 129 MoveBusMultiRegistrationWithinContext(this IBusController bus, IBusPeripheral peripheral, BusMultiRegistration newRegistration, ICPU cpu)130 public static void MoveBusMultiRegistrationWithinContext(this IBusController bus, IBusPeripheral peripheral, BusMultiRegistration newRegistration, ICPU cpu) 131 { 132 var regionName = newRegistration.ConnectionRegionName; 133 bus.MoveRegistrationWithinContext(peripheral, newRegistration, cpu, 134 selector: busRegisteredEnumerable => 135 { 136 return busRegisteredEnumerable.Where( 137 busRegistered => (busRegistered.RegistrationPoint is BusMultiRegistration multiRegistration) && multiRegistration.ConnectionRegionName == regionName 138 ).Single(); 139 } 140 ); 141 } 142 ZeroRange(this IBusController bus, long from, long size, ICPU context = null)143 public static void ZeroRange(this IBusController bus, long from, long size, ICPU context = null) 144 { 145 bus.ZeroRange(from.By(size), context); 146 } 147 GetSymbolAddress(this IBusController bus, string symbolName, int index, ICPU context = null)148 public static ulong GetSymbolAddress(this IBusController bus, string symbolName, int index, ICPU context = null) 149 { 150 if(!bus.TryGetAllSymbolAddresses(symbolName, out var addressesEnumerable, context)) 151 { 152 throw new RecoverableException($"Could not find any address for symbol: {symbolName}"); 153 } 154 var addresses = addressesEnumerable.ToArray(); 155 if(index < 0 || index >= addresses.Length) 156 { 157 var msg = (addresses.Length == 1) 158 ? "there is only one address" 159 : "there are only {addresses.Length} addresses"; 160 161 throw new RecoverableException($"Wrong index {index}: {msg} (0-based index) for '{symbolName}'"); 162 } 163 return addresses[index]; 164 } 165 GetSymbolAddress(this IBusController bus, string symbolName, ICPU context = null)166 public static ulong GetSymbolAddress(this IBusController bus, string symbolName, ICPU context = null) 167 { 168 if(!bus.TryGetAllSymbolAddresses(symbolName, out var addressesEnumerable, context)) 169 { 170 throw new RecoverableException($"Could not find any address for symbol: {symbolName}"); 171 } 172 var addresses = addressesEnumerable.ToArray(); 173 if(addresses.Length != 1) 174 { 175 throw new RecoverableException($"Found {addresses.Length} possible addresses for the symbol. Select which one you're interested in by providing a 0-based index or use the `GetAllSymbolAddresses` method"); 176 } 177 return addresses[0]; 178 } 179 180 // Specifying `textAddress` will override the address of the program text - the symbols will be applied 181 // as if the first loaded segment started at the specified address. This is equivalent to the ADDR parameter 182 // to GDB's add-symbol-file. LoadSymbolsFrom(this IBusController bus, ReadFilePath fileName, bool useVirtualAddress = false, ulong? textAddress = null, ICPU context = null)183 public static void LoadSymbolsFrom(this IBusController bus, ReadFilePath fileName, bool useVirtualAddress = false, ulong? textAddress = null, ICPU context = null) 184 { 185 using(var elf = ELFUtils.LoadELF(fileName)) 186 { 187 bus.LoadSymbolsFrom(elf, useVirtualAddress, textAddress, context); 188 } 189 } 190 } 191 } 192