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.Logging;
13 using Antmicro.Renode.Utilities;
14 using Antmicro.Renode.Core.Structure;
15 
16 namespace Antmicro.Renode.Peripherals.Bus
17 {
18     public class GaislerAHBPlugAndPlayInfo : IDoubleWordPeripheral
19     {
GaislerAHBPlugAndPlayInfo(IMachine machine)20         public GaislerAHBPlugAndPlayInfo(IMachine machine)
21         {
22             this.machine = machine;
23             Reset();
24         }
25         #region IDoubleWordPeripheral implementation
ReadDoubleWord(long offset)26         public uint ReadDoubleWord (long offset)
27         {
28             if(!recordsCached) //if first read
29             {
30                 cacheRecords();
31                 recordsCached = true;
32             }
33 
34             var deviceNumber = 0;
35             var master = false;
36             if (offset >= slaveOffset) //slave device record read
37             {
38                 deviceNumber = (int)(offset - slaveOffset) / 32;
39             }
40             else
41             {
42                 deviceNumber = (int)(offset) / 32;
43                 master = true;
44             }
45             var deviceRecord = getDeviceRecord(deviceNumber, master);
46             var recordOffset = (uint)((offset % 0x20)/4);
47             return deviceRecord.ToUintArray()[recordOffset];
48         }
49 
WriteDoubleWord(long offset, uint value)50         public void WriteDoubleWord (long offset, uint value)
51         {
52             this.Log(LogLevel.Warning,"Write attempt. This memory region is Read Only");
53         }
54         #endregion
55 
56         #region IPeripheral implementation
Reset()57         public void Reset ()
58         {
59             recordsCached = false;
60             emptyRecord = new GaislerAHBPlugAndPlayRecord();
61             masterDevices = new List<GaislerAHBPlugAndPlayRecord>();
62             slaveDevices = new List<GaislerAHBPlugAndPlayRecord>();
63         }
64         #endregion
65 
cacheRecords()66         private void cacheRecords()
67         {
68             //this.cacheMemory();
69             var recordsFound = machine.SystemBus.Children.Where(x => x.Peripheral is IGaislerAHB);
70             //.Cast<IRegistered<IGaislerAHB, IRegistrationPoint>>();
71             foreach (var record in recordsFound)
72             {
73                 var peripheral = (IGaislerAHB)record.Peripheral;
74                 var registration = record.RegistrationPoint;
75 
76                 var recordEntry = new GaislerAHBPlugAndPlayRecord();
77 
78                 var deviceAddress = registration.Range.StartAddress;
79 
80                 recordEntry.IdentificationRegister.Vendor = peripheral.GetVendorID();
81                 recordEntry.IdentificationRegister.Device = peripheral.GetDeviceID();
82                 recordEntry.BankAddressRegister[0].Type = peripheral.GetSpaceType();
83                 //XXX: hack
84                 if(recordEntry.IdentificationRegister.Vendor == 0x01 && recordEntry.IdentificationRegister.Device == 0x006)
85                 {
86                     deviceAddress -= PlugAndPlayRecordsOffset;
87                 }
88                 if(recordEntry.BankAddressRegister[0].Type == GaislerAHBPlugAndPlayRecord.SpaceType.AHBMemorySpace)
89                 {
90                     recordEntry.BankAddressRegister[0].Address = (uint)((deviceAddress >> 20) & 0xfff);
91                 }
92                 else if(recordEntry.BankAddressRegister[0].Type == GaislerAHBPlugAndPlayRecord.SpaceType.AHBIOSpace)
93                 {
94                     recordEntry.BankAddressRegister[0].Address = (uint)((deviceAddress >> 8) & 0xfff);
95                 }
96 
97                 recordEntry.BankAddressRegister[0].Mask = 0xfff;
98 
99                 if (peripheral.IsMaster())
100                 {
101                     masterDevices.Add(recordEntry);
102                 }
103                 else
104                 {
105                     slaveDevices.Add(recordEntry);
106                 }
107             }
108         }
109 
getDeviceRecord(int number, bool master)110         private GaislerAHBPlugAndPlayRecord getDeviceRecord(int number, bool master)
111         {
112             var record = emptyRecord;
113             if(master)
114             {
115                 if( number < masterDevices.Count)
116                 {
117                     record = masterDevices[number];
118                 }
119             }
120             else
121             {
122                 if( number < slaveDevices.Count)
123                 {
124                     record = slaveDevices[number];
125                 }
126             }
127             return record;
128         }
129 
130         private bool recordsCached;
131         private List<GaislerAHBPlugAndPlayRecord> masterDevices;
132         private List<GaislerAHBPlugAndPlayRecord> slaveDevices;
133         private GaislerAHBPlugAndPlayRecord emptyRecord;
134 
135         private readonly IMachine machine;
136         private readonly uint slaveOffset = 0x800;
137         private readonly uint PlugAndPlayRecordsOffset = 0xff000;
138     }
139 }
140 
141