1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Linq; 10 using System.Collections.Generic; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Utilities; 14 using Antmicro.Renode.Core.Structure; 15 using Antmicro.Renode.Core.Extensions; 16 using System.Net; 17 18 namespace Antmicro.Renode.Peripherals.Bus 19 { 20 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord)] 21 public class GaislerAPBController : IDoubleWordPeripheral, IGaislerAHB 22 { GaislerAPBController(IMachine machine)23 public GaislerAPBController(IMachine machine) 24 { 25 this.machine = machine; 26 Reset(); 27 } 28 29 #region IDoubleWordPeripheral implementation ReadDoubleWord(long offset)30 public uint ReadDoubleWord (long offset) 31 { 32 if(!recordsCached) 33 { 34 this.cacheRecords(); 35 recordsCached = true; 36 } 37 var record = emptyRecord; 38 var recordNumber = (int)(offset / 8); 39 if(recordNumber < records.Count) 40 { 41 record = records[recordNumber]; 42 } 43 var recordOffset = (int)((offset % 8) / 4); 44 return record.ToUintArray()[recordOffset]; 45 } 46 WriteDoubleWord(long offset, uint value)47 public void WriteDoubleWord (long offset, uint value) 48 { 49 //throw new NotImplementedException (); 50 } 51 #endregion 52 53 #region IPeripheral implementation Reset()54 public void Reset () 55 { 56 emptyRecord = new GaislerAPBPlugAndPlayRecord(); 57 recordsCached = false; 58 records = new List<GaislerAPBPlugAndPlayRecord>(); 59 } 60 #endregion 61 62 private readonly uint vendorID = 0x01; // Aeroflex Gaisler 63 private readonly uint deviceID = 0x006; // GRLIB APBCTRL 64 private readonly bool master = false; // This device is AHB slave 65 private readonly GaislerAHBPlugAndPlayRecord.SpaceType spaceType = GaislerAHBPlugAndPlayRecord.SpaceType.AHBMemorySpace; 66 67 #region IGaisslerAHB implementation GetVendorID()68 public uint GetVendorID () 69 { 70 return vendorID; 71 } 72 GetDeviceID()73 public uint GetDeviceID () 74 { 75 return deviceID; 76 } 77 IsMaster()78 public bool IsMaster () 79 { 80 return master; 81 } 82 GetSpaceType()83 public GaislerAHBPlugAndPlayRecord.SpaceType GetSpaceType () 84 { 85 return spaceType; 86 } 87 #endregion 88 GetBusAddress(IBusPeripheral peripheral)89 private uint? GetBusAddress(IBusPeripheral peripheral) 90 { 91 var registrationPoint = machine.SystemBus.GetRegistrationPoints(peripheral).SingleOrDefault(); 92 if(registrationPoint == null) 93 { 94 return null; 95 } 96 return (uint)(registrationPoint.Range.StartAddress >> 20) & 0xfff; 97 } 98 cacheRecords()99 private void cacheRecords() 100 { 101 var busAddress = GetBusAddress(this) ?? throw new RecoverableException("Failed to get the controller's bus address"); 102 var recordsFound = machine.SystemBus.Children 103 .Where(x => x.Peripheral is IGaislerAPB && GetBusAddress(x.Peripheral) == busAddress); 104 foreach (var record in recordsFound) 105 { 106 var peripheral = (IGaislerAPB)record.Peripheral; 107 var registration = record.RegistrationPoint; 108 var recordEntry = new GaislerAPBPlugAndPlayRecord(); 109 var deviceAddress = registration.Range.StartAddress; 110 var deviceSize = registration.Range.Size; 111 recordEntry.ConfigurationWord.Vendor = peripheral.GetVendorID(); 112 recordEntry.ConfigurationWord.Device = peripheral.GetDeviceID(); 113 recordEntry.BankAddressRegister.Type = peripheral.GetSpaceType(); 114 recordEntry.ConfigurationWord.Irq = peripheral.GetInterruptNumber(); 115 if(recordEntry.BankAddressRegister.Type == GaislerAPBPlugAndPlayRecord.SpaceType.APBIOSpace) 116 { 117 recordEntry.BankAddressRegister.Address = (uint)deviceAddress; 118 recordEntry.BankAddressRegister.Size = deviceSize; 119 } 120 records.Add(recordEntry); 121 } 122 } 123 124 private readonly IMachine machine; 125 private List<GaislerAPBPlugAndPlayRecord> records; 126 private bool recordsCached; 127 private GaislerAPBPlugAndPlayRecord emptyRecord; 128 } 129 } 130