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 System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Exceptions; 14 using Antmicro.Renode.Logging; 15 using Antmicro.Renode.Peripherals.Bus; 16 using Antmicro.Renode.Peripherals.Memory; 17 using Antmicro.Renode.Peripherals.MTD; 18 using static Antmicro.Renode.Peripherals.Bus.GaislerAPBPlugAndPlayRecord; 19 20 namespace Antmicro.Renode.Peripherals.MemoryControllers 21 { 22 public class Gaisler_FaultTolerantMemoryController : BasicDoubleWordPeripheral, IKnownSize, IGaislerAPB, 23 IPeripheralContainer<MappedMemory, NullRegistrationPoint>, IPeripheralContainer<AMDCFIFlash, NullRegistrationPoint> 24 { Gaisler_FaultTolerantMemoryController(IMachine machine)25 public Gaisler_FaultTolerantMemoryController(IMachine machine) : base(machine) 26 { 27 DefineRegisters(); 28 Reset(); 29 } 30 Reset()31 public override void Reset() 32 { 33 base.Reset(); 34 SetPromWriteEnable(false); 35 } 36 GetRegistrationPoints(MappedMemory peripheral)37 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(MappedMemory peripheral) 38 { 39 return prom != null ? 40 new [] { NullRegistrationPoint.Instance } : 41 Enumerable.Empty<NullRegistrationPoint>(); 42 } 43 Register(MappedMemory peripheral, NullRegistrationPoint registrationPoint)44 public void Register(MappedMemory peripheral, NullRegistrationPoint registrationPoint) 45 { 46 if(prom != null) 47 { 48 throw new RegistrationException("PROM MappedMemory already registered"); 49 } 50 51 machine.RegisterAsAChildOf(this, peripheral, registrationPoint); 52 prom = peripheral; 53 promAddress = sysbus.GetRegistrationPoints(prom).Single().Range.StartAddress; 54 } 55 Unregister(MappedMemory peripheral)56 public void Unregister(MappedMemory peripheral) 57 { 58 prom = null; 59 } 60 GetRegistrationPoints(AMDCFIFlash peripheral)61 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(AMDCFIFlash peripheral) 62 { 63 return flash != null ? 64 new [] { NullRegistrationPoint.Instance } : 65 Enumerable.Empty<NullRegistrationPoint>(); 66 } 67 Register(AMDCFIFlash peripheral, NullRegistrationPoint registrationPoint)68 public void Register(AMDCFIFlash peripheral, NullRegistrationPoint registrationPoint) 69 { 70 if(flash != null) 71 { 72 throw new RegistrationException("Flash already registered"); 73 } 74 75 machine.RegisterAsAChildOf(this, peripheral, registrationPoint); 76 flash = peripheral; 77 } 78 Unregister(AMDCFIFlash peripheral)79 public void Unregister(AMDCFIFlash peripheral) 80 { 81 flash = null; 82 } 83 84 public long Size => 0x100; 85 86 IEnumerable<IRegistered<MappedMemory, NullRegistrationPoint>> IPeripheralContainer<MappedMemory, NullRegistrationPoint>.Children 87 { 88 get => prom != null ? 89 new [] { Registered.Create(prom, NullRegistrationPoint.Instance) } : 90 Enumerable.Empty<IRegistered<MappedMemory, NullRegistrationPoint>>(); 91 } 92 93 IEnumerable<IRegistered<AMDCFIFlash, NullRegistrationPoint>> IPeripheralContainer<AMDCFIFlash, NullRegistrationPoint>.Children 94 { 95 get => flash != null ? 96 new [] { Registered.Create(flash, NullRegistrationPoint.Instance) } : 97 Enumerable.Empty<IRegistered<AMDCFIFlash, NullRegistrationPoint>>(); 98 } 99 DefineRegisters()100 private void DefineRegisters() 101 { 102 Registers.MemoryConfiguration1.Define(this) 103 .WithTag("promReadWaitStates", 0, 4) 104 .WithTag("promWriteWaitStates", 4, 4) 105 .WithTag("promWidth", 8, 2) 106 .WithReservedBits(10, 1) 107 .WithFlag(11, name: "promWriteEnable", changeCallback: (_, value) => SetPromWriteEnable(value)) 108 .WithReservedBits(12, 2) 109 .WithTag("promBankSize", 14, 3) 110 .WithReservedBits(18, 1) 111 .WithTaggedFlag("ioEnable", 19) 112 .WithTag("ioWaitStates", 20, 4) 113 .WithReservedBits(24, 1) 114 .WithTaggedFlag("busErrorCode", 25) 115 .WithTaggedFlag("ioBusReadyEnable", 26) 116 .WithTag("ioBusWidth", 27, 2) 117 .WithTaggedFlag("asynchronousBusReady", 29) 118 .WithTaggedFlag("promAreaBusReady", 30) 119 .WithReservedBits(31, 1); 120 121 Registers.MemoryConfiguration2.Define(this) 122 .WithTag("ramReadWaitStates", 0, 2) 123 .WithTag("ramWriteWaitStates", 2, 2) 124 .WithTag("ramWidth", 4, 2) 125 .WithTaggedFlag("readModifyWrite", 6) 126 .WithReservedBits(7, 2) 127 .WithTag("ramBankSize", 9, 4) 128 .WithTaggedFlag("sramDisable", 13) 129 .WithTaggedFlag("sdramEnable", 14) 130 .WithReservedBits(15, 4) 131 .WithTag("sdramCommand", 19, 2) 132 .WithTag("sdramColumnSize", 21, 2) 133 .WithTag("sdramBankSize", 23, 3) 134 .WithTaggedFlag("sdramTcas", 26) 135 .WithTag("sdramTrfc", 27, 3) 136 .WithTaggedFlag("sdramTrp", 30) 137 .WithTaggedFlag("sdramRefreshEnable", 31); 138 139 Registers.MemoryConfiguration3.Define(this) 140 .WithTag("testCheckbits", 0, 8) 141 .WithTaggedFlag("promEdacEnable", 8) 142 .WithTaggedFlag("ramEdacEnable", 9) 143 .WithTaggedFlag("edacDiagnosticReadBypass", 10) 144 .WithTaggedFlag("edacDiagnosticWriteBypass", 11) 145 .WithTag("sdramRefreshCounterReload", 12, 15) 146 .WithReservedBits(27, 1) 147 .WithTaggedFlag("reedSolomonEdacEnable", 28) 148 .WithReservedBits(29, 3); 149 150 Registers.MemoryConfiguration4.Define(this) 151 .WithTag("testCheckbits", 0, 16) 152 .WithTaggedFlag("edacDiagnosticWriteBypass", 16) 153 .WithReservedBits(17, 15); 154 } 155 SetPromWriteEnable(bool enable)156 private void SetPromWriteEnable(bool enable) 157 { 158 if(isWriteEnabled == enable) 159 { 160 return; 161 } 162 if(prom == null || flash == null) 163 { 164 this.ErrorLog("Attempted to set PROM write enable to {0} without a {1} (PROM) or {2} (flash) registered", 165 enable, nameof(MappedMemory), nameof(AMDCFIFlash)); 166 return; 167 } 168 this.DebugLog("Set PROM Write enable to {0}", enable); 169 if(enable) 170 { 171 sysbus.Unregister(prom); 172 sysbus.Register(flash, new BusPointRegistration(promAddress.Value)); 173 } 174 else 175 { 176 sysbus.Unregister(flash); 177 sysbus.Register(prom, new BusPointRegistration(promAddress.Value)); 178 } 179 isWriteEnabled = enable; 180 } 181 GetVendorID()182 public uint GetVendorID() => VendorID; 183 GetDeviceID()184 public uint GetDeviceID() => DeviceID; 185 GetInterruptNumber()186 public uint GetInterruptNumber() => 0; 187 GetSpaceType()188 public SpaceType GetSpaceType() => SpaceType.APBIOSpace; 189 190 private ulong? promAddress; 191 private bool isWriteEnabled; 192 private MappedMemory prom; 193 private AMDCFIFlash flash; 194 195 private const uint VendorID = 0x01; // Frontgrade Gaisler 196 private const uint DeviceID = 0x054; // FTMCTRL 197 198 private enum Registers : uint 199 { 200 MemoryConfiguration1 = 0x0, 201 MemoryConfiguration2 = 0x4, 202 MemoryConfiguration3 = 0x8, 203 MemoryConfiguration4 = 0xc, 204 } 205 } 206 } 207