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