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