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 
12 namespace Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIOModel
13 {
14     public class Interrupt
15     {
BuildRegisters(IProvidesRegisterCollection<DoubleWordRegisterCollection> owner, int count, string name, System.Enum flagOffset, System.Enum enableOffset)16         public static IReadOnlyList<Interrupt> BuildRegisters(IProvidesRegisterCollection<DoubleWordRegisterCollection> owner, int count, string name, System.Enum flagOffset, System.Enum enableOffset)
17         {
18             var flagRegister = flagOffset.Define(owner)
19                 .WithReservedBits(count, 32 - count);
20             var enableRegister = enableOffset.Define(owner)
21                 .WithReservedBits(count, 32 - count);
22 
23             return Enumerable.Range(0, count).Select(index =>
24                 {
25                     Interrupt interrupt = null;
26                     var flag = flagRegister.DefineFlagField(index, FieldMode.Read | FieldMode.WriteOneToClear, name: $"{name}Flag",
27                         changeCallback: (prev, val) => interrupt.OnFlagChange(prev, val)
28                     );
29                     var enable = enableRegister.DefineFlagField(index, name: $"{name}Enable",
30                         changeCallback: (prev, val) => interrupt.OnMaskChange(prev, val)
31                     );
32                     interrupt = new Interrupt(flag, enable);
33                     return interrupt;
34                 }
35             ).ToList().AsReadOnly();
36         }
37 
Reset()38         public void Reset()
39         {
40             isFlagUnchangeable = false;
41         }
42 
SetFlag(bool value, bool unchangeableFlag = false)43         public void SetFlag(bool value, bool unchangeableFlag = false)
44         {
45             isFlagUnchangeable = unchangeableFlag;
46             if(flag.Value != value)
47             {
48                 flag.Value = value;
49                 HandleChange(!value, mask.Value);
50             }
51         }
52 
53         public bool MaskedFlag => flag.Value && mask.Value;
54 
55         public event Action<bool> MaskedFlagChanged;
56 
Interrupt(IFlagRegisterField flag, IFlagRegisterField mask)57         private Interrupt(IFlagRegisterField flag, IFlagRegisterField mask)
58         {
59             this.flag = flag;
60             this.mask = mask;
61         }
62 
OnFlagChange(bool previousValue, bool value)63         private void OnFlagChange(bool previousValue, bool value)
64         {
65             if(isFlagUnchangeable)
66             {
67                 flag.Value = previousValue;
68                 return;
69             }
70             HandleChange(previousValue, mask.Value);
71         }
72 
OnMaskChange(bool previousValue, bool value)73         private void OnMaskChange(bool previousValue, bool value)
74         {
75             HandleChange(flag.Value, previousValue);
76         }
77 
HandleChange(bool previousFlag, bool previousMask)78         private void HandleChange(bool previousFlag, bool previousMask)
79         {
80             var previousMasked = previousFlag && previousMask;
81             if(previousMasked != MaskedFlag)
82             {
83                 MaskedFlagChanged?.Invoke(MaskedFlag);
84             }
85         }
86 
87         private bool isFlagUnchangeable;
88         private readonly IFlagRegisterField flag;
89         private readonly IFlagRegisterField mask;
90     }
91 }
92