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.Structure.Registers; 11 using Antmicro.Renode.Logging; 12 using static Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIO; 13 14 namespace Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIOModel 15 { 16 public class Shifter : ResourceBlock 17 { BuildRegisters(IResourceBlockOwner owner, int count, ResourceBlocksManager<Timer> timersManager)18 public static IReadOnlyList<Shifter> BuildRegisters(IResourceBlockOwner owner, int count, ResourceBlocksManager<Timer> timersManager) 19 { 20 var statusFlags = Interrupt.BuildRegisters(owner, count, "ShifterStatus", Registers.ShifterStatus, Registers.ShifterStatusInterruptEnable); 21 var errorFlags = Interrupt.BuildRegisters(owner, count, "ShifterError", Registers.ShifterError, Registers.ShifterErrorInterruptEnable); 22 23 return Enumerable.Range(0, count) 24 .Select(index => BuildShifter(owner, index, statusFlags[index], errorFlags[index], timersManager)) 25 .ToList().AsReadOnly(); 26 } 27 Reset()28 public override void Reset() 29 { 30 base.Reset(); 31 receiveBuffer.Clear(); 32 } 33 OnDataReceive(uint data)34 public void OnDataReceive(uint data) 35 { 36 if(mode.Value != ShifterMode.Receive) 37 { 38 owner.Log(LogLevel.Warning, "Trying to receive data (0x{0:X}) using the shifter with ID {1} that isn't in the receive mode", data, Identifier); 39 return; 40 } 41 42 receiveBuffer.Enqueue(data); 43 if(receiveBuffer.Count == 1) 44 { 45 // Trigger an interrupt when there was no data in the buffer before. 46 buffer.Value = data; 47 Status.SetFlag(true); 48 } 49 } 50 51 public event Action<uint> DataTransmitted; 52 public event Action ControlOrConfigurationChanged; 53 54 public override IEnumerable<Interrupt> Interrupts => new[] { Status, Error }; 55 public override string Name => $"Shifter{Identifier}"; 56 57 public Interrupt Status { get; } 58 public Interrupt Error { get; } 59 public Timer Timer 60 { 61 get 62 { 63 timersManager.TryGet((uint)timerSelect.Value, out var timer); 64 return timer; 65 } 66 } 67 public ShifterPolarity TimerPolarity => timerPolarity.Value; 68 public ShifterMode Mode => mode.Value; 69 public uint StopBit => (uint)stopBit.Value; 70 public uint StartBit => (uint)startBit.Value; 71 BuildShifter(IResourceBlockOwner owner, int index, Interrupt status, Interrupt error, ResourceBlocksManager<Timer> timersManager)72 private static Shifter BuildShifter(IResourceBlockOwner owner, int index, Interrupt status, Interrupt error, 73 ResourceBlocksManager<Timer> timersManager) 74 { 75 Shifter shifter = null; 76 var offset = index * 4; 77 78 var bufferField = (Registers.ShifterBuffer0 + offset).Define(owner) 79 .DefineValueField(0, 32, name: $"SHIFTBUF (Shifter Buffer)", 80 writeCallback: (prev, val) => shifter.OnBufferWrite((uint)val), 81 readCallback: (_, __) => shifter.OnBufferRead() 82 ); 83 84 var controlRegister = (Registers.ShifterControl0 + offset).Define(owner) 85 .WithReservedBits(27, 5) 86 .WithReservedBits(18, 5) 87 .WithTag("PINCFG (Shifter Pin Configuration)", 16, 2) 88 .WithReservedBits(13, 3) 89 .WithTag("PINSEL (Shifter Pin Select)", 8, 5) 90 .WithTaggedFlag("PINPOL (Shifter Pin Polarity)", 7) 91 .WithReservedBits(3, 4); 92 93 var timerSelectField = controlRegister.DefineValueField(24, 3, name: "TIMSEL (Timer Select)"); 94 var timerPolarityField = controlRegister.DefineEnumField<ShifterPolarity>(23, 1, name: "TIMPOL (Timer Polarity)"); 95 var modeField = controlRegister.DefineEnumField<ShifterMode>(0, 3, name: $"SMOD (Shifter Mode)", changeCallback: (__, val) => shifter.OnModeChange(val)); 96 controlRegister.WithChangeCallback((_, __) => shifter.OnControlOrConfigurationChange()); 97 98 var configurationRegister = (Registers.ShifterConfiguration0 + offset).Define(owner) 99 .WithReservedBits(21, 11) 100 .WithTag("PWIDTH (Parallel Width)", 16, 5) 101 .WithReservedBits(13, 3) 102 .WithTaggedFlag("SSIZE (Shifter Size)", 12) 103 .WithReservedBits(10, 2) 104 .WithTaggedFlag("LATST (Late Store)", 9) 105 .WithTaggedFlag("INSRC (Input Source)", 8) 106 .WithReservedBits(6, 2) 107 .WithReservedBits(2, 2); 108 109 var stopBitField = configurationRegister.DefineValueField(4, 2, name: "SSTOP (Shifter Stop Bit)"); 110 var startBitField = configurationRegister.DefineValueField(0, 2, name: "SSTART (Shifter Start Bit)"); 111 configurationRegister.WithChangeCallback((_, __) => shifter.OnControlOrConfigurationChange()); 112 113 DefineStubRegisters(owner, offset); 114 shifter = new Shifter( 115 owner, 116 (uint)index, 117 timersManager, 118 status, 119 error, 120 bufferField, 121 timerSelectField, 122 timerPolarityField, 123 modeField, 124 stopBitField, 125 startBitField 126 ); 127 return shifter; 128 } 129 DefineStubRegisters(IProvidesRegisterCollection<DoubleWordRegisterCollection> owner, int offset)130 private static void DefineStubRegisters(IProvidesRegisterCollection<DoubleWordRegisterCollection> owner, int offset) 131 { 132 (Registers.ShifterBuffer0BitSwapped + offset).Define(owner).WithTag("SHIFTBUFBIS (Shifter Buffer Bit Swapped)", 0, 32); 133 (Registers.ShifterBuffer0ByteSwapped + offset).Define(owner).WithTag("SHIFTBUFBYS (Shifter Buffer Byte Swapped)", 0, 32); 134 (Registers.ShifterBuffer0BitByteSwapped + offset).Define(owner).WithTag("SHIFTBUFBBS (Shifter Buffer Bit Byte Swapped)", 0, 32); 135 (Registers.ShifterBuffer0NibbleByteSwapped + offset).Define(owner).WithTag("SHIFTBUFNBS (Shifter Buffer Nibble Byte Swapped)", 0, 32); 136 (Registers.ShifterBuffer0HalfwordSwapped + offset).Define(owner).WithTag("SHIFTBUFHWS (Shifter Buffer Halfword Swapped)", 0, 32); 137 (Registers.ShifterBuffer0NibbleSwapped + offset).Define(owner).WithTag("SHIFTBUFNIS (Shifter Buffer Nibble Swapped)", 0, 32); 138 (Registers.ShifterBuffer0OddEvenSwapped + offset).Define(owner).WithTag("SHIFTBUFOES (Shifter Buffer Odd Even Swapped)", 0, 32); 139 (Registers.ShifterBuffer0EvenOddSwapped + offset).Define(owner).WithTag("SHIFTBUFEOS (Shifter Buffer Even Odd Swapped)", 0, 32); 140 (Registers.ShifterBuffer0HalfWordByteSwapped + offset).Define(owner).WithTag("SHIFTBUFHBS (Shifter Buffer Half Word Byte Swapped)", 0, 32); 141 } 142 Shifter(IResourceBlockOwner owner, uint identifier, ResourceBlocksManager<Timer> timersManager, Interrupt status, Interrupt error, IValueRegisterField buffer, IValueRegisterField timerSelect, IEnumRegisterField<ShifterPolarity> timerPolarity, IEnumRegisterField<ShifterMode> mode, IValueRegisterField stopBit, IValueRegisterField startBit)143 private Shifter(IResourceBlockOwner owner, uint identifier, ResourceBlocksManager<Timer> timersManager, 144 Interrupt status, Interrupt error, 145 IValueRegisterField buffer, 146 IValueRegisterField timerSelect, IEnumRegisterField<ShifterPolarity> timerPolarity, IEnumRegisterField<ShifterMode> mode, 147 IValueRegisterField stopBit, IValueRegisterField startBit) : base(owner, identifier) 148 { 149 this.timersManager = timersManager; 150 Status = status; 151 Error = error; 152 153 this.buffer = buffer; 154 this.timerSelect = timerSelect; 155 this.timerPolarity = timerPolarity; 156 this.mode = mode; 157 this.stopBit = stopBit; 158 this.startBit = startBit; 159 160 Status.MaskedFlagChanged += OnInterruptChange; 161 Error.MaskedFlagChanged += OnInterruptChange; 162 } 163 OnControlOrConfigurationChange()164 private void OnControlOrConfigurationChange() 165 { 166 ControlOrConfigurationChanged?.Invoke(); 167 } 168 OnModeChange(ShifterMode value)169 private void OnModeChange(ShifterMode value) 170 { 171 if(value == ShifterMode.Transmit) 172 { 173 Status.SetFlag(true); 174 } 175 } 176 OnBufferWrite(uint data)177 private void OnBufferWrite(uint data) 178 { 179 if(mode.Value != ShifterMode.Transmit) 180 { 181 owner.Log(LogLevel.Warning, "Writing data (0x{0:X}) to the buffer of the shifter with ID {1} that isn't in the transmit mode", data, Identifier); 182 return; 183 } 184 185 Status.SetFlag(false); 186 DataTransmitted?.Invoke(data); 187 } 188 OnBufferRead()189 private void OnBufferRead() 190 { 191 if(mode.Value != ShifterMode.Receive) 192 { 193 owner.Log(LogLevel.Warning, "Reading data from the buffer of the shifter with ID {0} that isn't in the receive mode", Identifier); 194 return; 195 } 196 197 // Discard read value from the buffer. 198 if(receiveBuffer.Count > 0) 199 { 200 receiveBuffer.Dequeue(); 201 } 202 RefreshBuffer(); 203 } 204 RefreshBuffer()205 private void RefreshBuffer() 206 { 207 var hasMoreData = receiveBuffer.Count > 0; 208 if(hasMoreData) 209 { 210 buffer.Value = receiveBuffer.Peek(); 211 } 212 Status.SetFlag(hasMoreData); 213 } 214 215 private readonly ResourceBlocksManager<Timer> timersManager; 216 private readonly IValueRegisterField buffer; 217 private readonly Queue<uint> receiveBuffer = new Queue<uint>(); 218 private readonly IValueRegisterField timerSelect; 219 private readonly IEnumRegisterField<ShifterPolarity> timerPolarity; 220 private readonly IEnumRegisterField<ShifterMode> mode; 221 private readonly IValueRegisterField stopBit; 222 private readonly IValueRegisterField startBit; 223 } 224 225 public enum ShifterPolarity 226 { 227 OnPosedge = 0, 228 OnNegedge = 1 229 } 230 231 public enum ShifterMode 232 { 233 Disabled = 0b000, 234 Receive = 0b001, 235 Transmit = 0b010, 236 Reserved = 0b011, 237 MatchStore = 0b100, 238 MatchContinuous = 0b101, 239 State = 0b110, 240 Logic = 0b111 241 } 242 } 243