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