1 //
2 // Copyright (c) 2010-2018 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 
9 using Antmicro.Renode.Core;
10 using Antmicro.Renode.Logging;
11 using Antmicro.Renode.Peripherals.Bus;
12 using System.Linq;
13 using Antmicro.Migrant;
14 using System;
15 using System.Collections.Generic;
16 using System.Collections.ObjectModel;
17 
18 namespace Antmicro.Renode.Peripherals.IRQControllers
19 {
20 	public class SIC : IDoubleWordPeripheral, INumberedGPIOOutput, IIRQController
21 	{
SIC()22 		public SIC()
23 		{
24 			parent = Enumerable.Range(0, 32).ToArray();
25             var innerConnections = new Dictionary<int, IGPIO>();
26             for(var i = 0; i < 32; i++)
27             {
28                 innerConnections[i] = new GPIO();
29             }
30             Connections = new ReadOnlyDictionary<int, IGPIO>(innerConnections);
31 
32 			irq = 31;
33 		}
34 
ReadDoubleWord(long offset)35 		public uint ReadDoubleWord(long offset)
36 		{
37             lock(sync)
38             {
39     			switch ((SR)(offset >> 2))
40     			{
41     			case SR.Status:
42     				return level & mask;
43     			case SR.RawStatus:
44     				return level;
45     			case SR.Enable:
46     				return mask;
47     			case SR.SoftInterrupt:
48     				return level & 1;
49     			case SR.PICEnable:
50     				return picEnable;
51     			default:
52     				this.LogUnhandledRead(offset);
53     				return 0u;
54     			}
55             }
56 		}
57 
WriteDoubleWord(long offset, uint value)58 		public void WriteDoubleWord(long offset, uint value)
59 		{
60             lock(sync)
61             {
62     			switch ((SR)(offset >> 2))
63     			{
64     			case SR.Enable:
65     				mask |= value;
66     				break;
67     			case SR.EnableClear:
68     				mask &= ~value;
69     				break;
70     			case SR.SoftInterrupt:
71     				if (value > 0)
72     				{
73     					mask |= 1u;
74     				}
75     				break;
76     			case SR.SoftInterruptClear:
77     				if (value > 0)
78     				{
79     					mask &= ~1u;
80     				}
81     				break;
82     			case SR.PICEnable:
83     				picEnable |= (value & 0x7FE00000);
84     				UpdatePIC();
85     				break;
86     			case SR.PICEnableClear:
87     				picEnable &= ~value;
88     				UpdatePIC();
89     				break;
90     			default:
91     				this.LogUnhandledWrite(offset, value);
92     				return;
93     			}
94     			Update();
95             }
96 		}
97 
Reset()98 		public void Reset()
99 		{
100 			// TODO: some kind of reset?
101 		}
102 
OnGPIO(int irq, bool value)103         public void OnGPIO(int irq, bool value)
104         {
105             lock(sync)
106             {
107                 if (value)
108                 {
109                     level |= 1u << irq;
110                 }
111                 else
112                 {
113                     level &= ~(1u << irq);
114                 }
115                 if ((picEnable & (1u << irq)) > 0)
116                 {
117                     Connections[parent[irq]].Set(value);
118                 }
119                 Update();
120             }
121         }
122 
Update()123 		private void Update()
124 		{
125 			this.DebugLog("Update.");
126 			var flags = level & mask;
127 			Connections[irq].Set(flags != 0);
128 		}
129 
UpdatePIC()130 		private void UpdatePIC()
131 		{
132 			for (var i = 21; i <= 30; i++)
133 			{
134 				var mask = 1u << i;
135 				if ((picEnable & mask) == 0)
136 				{
137 					continue;
138 				}
139                 Connections[parent[i]].Set((level & mask) != 0);
140 			}
141 		}
142 
143 		private uint level;
144 		private uint mask;
145 		private uint picEnable;
146 		private int[] parent;
147         public IReadOnlyDictionary<int, IGPIO> Connections { get; private set; }
148 		private readonly int irq;
149 
150         [Constructor]
151         private object sync = new object();
152 
153 		private enum SR : uint
154 		{
155 			Status = 0x0,
156 			RawStatus = 0x1,
157 			Enable = 0x2,
158 			EnableClear = 0x3,
159 			SoftInterrupt = 0x4,
160 			SoftInterruptClear = 0x5,
161 			PICEnable = 0x8,
162 			PICEnableClear = 0x9,
163 		}
164 	}
165 }
166 
167