1 //
2 // Copyright (c) 2010-2018 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.Collections.Generic;
8 using Antmicro.Renode.Core;
9 using Antmicro.Renode.Utilities;
10 
11 namespace Antmicro.Renode.Peripherals
12 {
13     public class InterruptHandler<TRegister, TFlag>
14     {
InterruptHandler(IGPIO gpio)15         public InterruptHandler(IGPIO gpio)
16         {
17             irqs = new Dictionary<TRegister, IrqState>();
18             flagToRegister = new Dictionary<TFlag, FlagState>();
19             this.gpio = gpio;
20         }
21 
Reset()22         public void Reset()
23         {
24             foreach(var irq in irqs)
25             {
26                 irq.Value.Value = 0;
27                 irq.Value.Mask = 0;
28             }
29             gpio.Unset();
30         }
31 
RegisterInterrupt(TRegister register, TFlag flag, byte position, bool masked = false)32         public void RegisterInterrupt(TRegister register, TFlag flag, byte position, bool masked = false)
33         {
34             if(!irqs.ContainsKey(register))
35             {
36                 irqs[register] = new IrqState();
37             }
38 
39             flagToRegister.Add(flag, new FlagState { Position = position, Register = register });
40             if(masked)
41             {
42                 BitHelper.SetBit(ref irqs[register].Mask, position, true);
43             }
44         }
45 
RequestInterrupt(TFlag flag)46         public void RequestInterrupt(TFlag flag)
47         {
48             var reg = flagToRegister[flag];
49             BitHelper.SetBit(ref irqs[reg.Register].Value, reg.Position, true);
50             Refresh();
51         }
52 
GetRegisterValue(TRegister register)53         public uint GetRegisterValue(TRegister register)
54         {
55             return irqs[register].Value;
56         }
57 
SetRegisterValue(TRegister register, uint value)58         public void SetRegisterValue(TRegister register, uint value)
59         {
60             irqs[register].Value = value;
61             Refresh();
62         }
63 
GetRegisterMask(TRegister register)64         public uint GetRegisterMask(TRegister register)
65         {
66             return irqs[register].Mask;
67         }
68 
SetRegisterMask(TRegister register, uint value)69         public void SetRegisterMask(TRegister register, uint value)
70         {
71             irqs[register].Mask = value;
72             Refresh();
73         }
74 
Refresh()75         public void Refresh()
76         {
77             foreach(var flag in flagToRegister)
78             {
79                 if(BitHelper.IsBitSet(irqs[flag.Value.Register].EffectiveValue, flag.Value.Position))
80                 {
81                     gpio.Set(true);
82                     return;
83                 }
84             }
85             gpio.Set(false);
86         }
87 
88         private readonly Dictionary<TRegister, IrqState> irqs;
89         private readonly Dictionary<TFlag, FlagState> flagToRegister;
90         private readonly IGPIO gpio;
91 
92         private class IrqState
93         {
94             public uint Value;
95             public uint Mask;
96 
97             public uint EffectiveValue { get { return Value & Mask; } }
98         }
99 
100         private class FlagState
101         {
102             public TRegister Register;
103             public byte Position;
104         }
105     }
106 }
107