1 // 2 // Copyright (c) 2010-2025 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; 11 using Antmicro.Renode.Core.Structure; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Exceptions; 14 using Antmicro.Renode.Logging; 15 using Antmicro.Renode.Network; 16 using Antmicro.Renode.Peripherals.Bus; 17 using Antmicro.Renode.Peripherals.CPU; 18 using Antmicro.Renode.Peripherals.Timers; 19 using Antmicro.Renode.Time; 20 using Antmicro.Renode.Utilities; 21 using PacketDotNet; 22 23 namespace Antmicro.Renode.Peripherals.Network 24 { 25 public partial class SynopsysDWCEthernetQualityOfService : NetworkWithPHY, IMACInterface, IKnownSize 26 { SynopsysDWCEthernetQualityOfService(IMachine machine, long systemClockFrequency, ICPU cpuContext = null)27 public SynopsysDWCEthernetQualityOfService(IMachine machine, long systemClockFrequency, ICPU cpuContext = null) : base(machine) 28 { 29 if(DMAChannelOffsets.Length < 1 || DMAChannelOffsets.Length > MaxDMAChannels) 30 { 31 throw new ConstructionException($"Invalid DMA channel count {DMAChannelOffsets.Length}. Expected value between 1 and {MaxDMAChannels}"); 32 } 33 34 IRQ = new GPIO(); 35 MAC = EmulationManager.Instance.CurrentEmulation.MACRepository.GenerateUniqueMAC(); 36 MAC1 = EmulationManager.Instance.CurrentEmulation.MACRepository.GenerateUniqueMAC(); 37 Bus = machine.GetSystemBus(this); 38 this.CpuContext = cpuContext; 39 40 dmaChannels = new DMAChannel[DMAChannelOffsets.Length]; 41 for(var i = 0; i < dmaChannels.Length; i++) 42 { 43 dmaChannels[i] = new DMAChannel(this, i, systemClockFrequency, SeparateDMAInterrupts); 44 } 45 46 rxIpcPacketCounterInterruptEnable = new IFlagRegisterField[NumberOfIpcCounters]; 47 rxIpcByteCounterInterruptEnable = new IFlagRegisterField[NumberOfIpcCounters]; 48 rxIpcPacketCounterInterrupt = new IFlagRegisterField[NumberOfIpcCounters]; 49 rxIpcByteCounterInterrupt = new IFlagRegisterField[NumberOfIpcCounters]; 50 rxIpcPacketCounter = new IValueRegisterField[NumberOfIpcCounters]; 51 rxIpcByteCounter = new IValueRegisterField[NumberOfIpcCounters]; 52 macAndMmcRegisters = new DoubleWordRegisterCollection(this, CreateRegisterMap()); 53 mtlRegisters = new DoubleWordRegisterCollection(this, CreateMTLRegisterMap()); 54 dmaRegisters = new DoubleWordRegisterCollection(this, CreateDMARegisterMap()); 55 } 56 ReceiveFrame(EthernetFrame frame)57 public void ReceiveFrame(EthernetFrame frame) 58 { 59 if(!rxEnable.Value) 60 { 61 this.Log(LogLevel.Debug, "Receive: Dropping frame {0}", frame); 62 return; 63 } 64 65 var channelCount = dmaChannels.Length; 66 67 // If only one channel is specified packetDuplicationControl and dmaChannelSelect fields will be null, so 68 // route the packet to the only available channel and return early 69 if(channelCount == 1) 70 { 71 dmaChannels[0].ReceiveFrame(frame); 72 return; 73 } 74 75 if(packetDuplicationControl.Value) 76 { 77 // With packet duplication enabled each set bit in the DCS field encodes a DMA channel that should receive the frame 78 BitHelper.ForeachActiveBit(dmaChannelSelect.Value, bit => dmaChannels[bit].ReceiveFrame(frame)); 79 } 80 else 81 { 82 // DCS encodes a DMA channel number when packet duplication control is disabled 83 var channel = (int)dmaChannelSelect.Value; 84 if(channel >= channelCount) 85 { 86 this.WarningLog("DMA channel number {0} is not in range of [0, {1}). Dropping packet", channel, channelCount); 87 return; 88 } 89 90 dmaChannels[channel].ReceiveFrame(frame); 91 } 92 } 93 Reset()94 public override void Reset() 95 { 96 ResetRegisters(); 97 foreach(var channel in dmaChannels) 98 { 99 channel.Reset(); 100 } 101 UpdateInterrupts(); 102 } 103 104 public virtual long Size => 0xC00; 105 [DefaultInterrupt] 106 public GPIO IRQ { get; } 107 public MACAddress MAC { get; set; } 108 public MACAddress MAC0 => MAC; 109 public MACAddress MAC1 { get; set; } 110 111 public event Action<EthernetFrame> FrameReady; 112 113 // Configuration options for derived classes 114 115 // Offset at which each channel should start. This also determinates the amount of DMA channels 116 protected virtual long[] DMAChannelOffsets => new long[]{ 0x100 }; 117 protected virtual BusWidth DMABusWidth => BusWidth.Bits32; 118 protected virtual int RxQueueSize => 8192; 119 protected virtual bool SeparateDMAInterrupts => false; 120 SendFrame(EthernetFrame frame)121 private void SendFrame(EthernetFrame frame) 122 { 123 if(loopbackEnabled.Value) 124 { 125 ReceiveFrame(frame); 126 } 127 else 128 { 129 FrameReady?.Invoke(frame); 130 } 131 132 IncrementPacketCounter(txGoodPacketCounter, txGoodPacketCounterInterrupt); 133 IncrementPacketCounter(txPacketCounter, txPacketCounterInterrupt); 134 // one added to account for Start of Frame Delimiter (SFD) 135 var byteCount = 1 + (uint)frame.Bytes.Length; 136 IncrementByteCounter(txByteCounter, txByteCounterInterrupt, byteCount); 137 IncrementByteCounter(txGoodByteCounter, txGoodByteCounterInterrupt, byteCount); 138 if(frame.DestinationMAC.IsBroadcast) 139 { 140 IncrementPacketCounter(txBroadcastPacketCounter, txBroadcastPacketCounterInterrupt); 141 } 142 else if(frame.DestinationMAC.IsMulticast) 143 { 144 IncrementPacketCounter(txMulticastPacketCounter, txMulticastPacketCounterInterrupt); 145 } 146 else 147 { 148 IncrementPacketCounter(txUnicastPacketCounter, txUnicastPacketCounterInterrupt); 149 } 150 #if DEBUG 151 this.Log(LogLevel.Noisy, "Transmission: frame {0}", Misc.PrettyPrintCollectionHex(frame.Bytes)); 152 this.Log(LogLevel.Debug, "Transmission: frame {0}", frame); 153 #endif 154 } 155 UpdateRxCounters(EthernetFrame frame, RxDescriptor.NormalWriteBackDescriptor writeBackStructure)156 private void UpdateRxCounters(EthernetFrame frame, RxDescriptor.NormalWriteBackDescriptor writeBackStructure) 157 { 158 if(writeBackStructure.crcError) 159 { 160 IncrementPacketCounter(rxCrcErrorPacketCounter, rxCrcErrorPacketCounterInterrupt); 161 } 162 IncrementPacketCounter(rxPacketCounter, rxPacketCounterInterrupt); 163 // byte count excludes preamble, one added to account for Start of Frame Delimiter (SFD) 164 var byteCount = 1 + writeBackStructure.packetLength; 165 IncrementByteCounter(rxByteCounter, rxByteCounterInterrupt, byteCount); 166 167 var isRuntPacket = writeBackStructure.packetLength <= EthernetFrame.RuntPacketMaximumSize; 168 var lengthOutOfRange = frame.Length > EthernetFrame.MaximumFrameSize; 169 var isNontypePacket = (writeBackStructure.lengthTypeField != PacketKind.TypePacket); 170 var lengthMismatch = (frame.Length != writeBackStructure.packetLength); 171 172 var lengthError = isNontypePacket && lengthMismatch; 173 var outOfRange = isNontypePacket && lengthOutOfRange; 174 if(writeBackStructure.crcError || isRuntPacket || lengthError || outOfRange) 175 { 176 return; 177 } 178 179 IncrementByteCounter(rxGoodByteCounter, rxGoodByteCounterInterrupt, byteCount); 180 if(frame.DestinationMAC.IsBroadcast) 181 { 182 IncrementPacketCounter(rxBroadcastPacketCounter, rxBroadcastPacketCounterInterrupt); 183 } 184 else if(frame.DestinationMAC.IsMulticast) 185 { 186 IncrementPacketCounter(rxMulticastPacketCounter, rxMulticastPacketCounterInterrupt); 187 } 188 else 189 { 190 IncrementPacketCounter(rxUnicastPacketCounter, rxUnicastPacketCounterInterrupt); 191 } 192 193 if(writeBackStructure.ipv4HeaderPresent) 194 { 195 IncreaseIpcCounter(IpcCounter.IpV4Good, byteCount); 196 if(writeBackStructure.ipHeaderError) 197 { 198 IncreaseIpcCounter(IpcCounter.IpV4HeaderError, byteCount); 199 } 200 } 201 if(writeBackStructure.ipv6HeaderPresent) 202 { 203 IncreaseIpcCounter(IpcCounter.IpV6Good, byteCount); 204 if(writeBackStructure.ipHeaderError) 205 { 206 IncreaseIpcCounter(IpcCounter.IpV6HeaderError, byteCount); 207 } 208 } 209 if(writeBackStructure.payloadType == PayloadType.UDP) 210 { 211 IncreaseIpcCounter(IpcCounter.UdpGood, byteCount); 212 } 213 else if(writeBackStructure.payloadType == PayloadType.TCP) 214 { 215 IncreaseIpcCounter(IpcCounter.TcpGood, byteCount); 216 } 217 else if(writeBackStructure.payloadType == PayloadType.ICMP) 218 { 219 IncreaseIpcCounter(IpcCounter.IcmpGood, byteCount); 220 } 221 } 222 IncrementPacketCounter(IValueRegisterField counter, IFlagRegisterField status)223 private void IncrementPacketCounter(IValueRegisterField counter, IFlagRegisterField status) 224 { 225 counter.Value += 1; 226 status.Value |= EqualsHalfOrMaximumCounterValue(counter); 227 } 228 IncrementByteCounter(IValueRegisterField counter, IFlagRegisterField status, uint increment)229 private void IncrementByteCounter(IValueRegisterField counter, IFlagRegisterField status, uint increment) 230 { 231 status.Value |= WouldExceedHalfOrMaximumCounterValue(counter, increment); 232 counter.Value += increment; 233 } 234 IncreaseIpcCounter(IpcCounter type, uint byteCount)235 private void IncreaseIpcCounter(IpcCounter type, uint byteCount) 236 { 237 var index = (int)type; 238 IncrementPacketCounter(rxIpcPacketCounter[index], rxIpcPacketCounterInterrupt[index]); 239 IncrementByteCounter(rxIpcByteCounter[index], rxIpcByteCounterInterrupt[index], byteCount); 240 } 241 CheckAnySetIpcCounterInterrupts()242 private bool CheckAnySetIpcCounterInterrupts() 243 { 244 for(var i = 0; i < NumberOfIpcCounters; i++) 245 { 246 if((rxIpcPacketCounterInterrupt[i].Value && rxIpcPacketCounterInterruptEnable[i].Value) || (rxIpcByteCounterInterrupt[i].Value && rxIpcByteCounterInterruptEnable[i].Value)) 247 { 248 return true; 249 } 250 } 251 return false; 252 } 253 EqualsHalfOrMaximumCounterValue(IValueRegisterField counter)254 private bool EqualsHalfOrMaximumCounterValue(IValueRegisterField counter) 255 { 256 return (counter.Value == CounterMaxValue) || (counter.Value == (CounterMaxValue / 2)); 257 } 258 WouldExceedHalfOrMaximumCounterValue(IValueRegisterField counter, uint increment)259 private bool WouldExceedHalfOrMaximumCounterValue(IValueRegisterField counter, uint increment) 260 { 261 return (counter.Value < CounterMaxValue && counter.Value + increment >= CounterMaxValue) 262 || (counter.Value < CounterMaxValue / 2 && counter.Value + increment >= CounterMaxValue / 2); 263 } 264 UpdateInterrupts()265 private void UpdateInterrupts() 266 { 267 var dmaInterrupt = false; 268 foreach(var channel in dmaChannels) 269 { 270 dmaInterrupt |= channel.UpdateInterrupts(); 271 } 272 273 var irq = (ptpMessageTypeInterrupt.Value && ptpMessageTypeInterruptEnable.Value) || 274 (lowPowerIdleInterrupt.Value && lowPowerIdleInterruptEnable.Value) || 275 (timestampInterrupt.Value && timestampInterruptEnable.Value) || 276 dmaInterrupt || 277 MMCTxInterruptStatus || 278 MMCRxInterruptStatus || 279 CheckAnySetIpcCounterInterrupts(); 280 281 this.Log(LogLevel.Noisy, "Setting IRQ: {0}", irq); 282 IRQ.Set(irq); 283 } 284 285 private IBusController Bus { get; } 286 private ICPU CpuContext { get; } 287 288 private bool MMCTxInterruptStatus => 289 (txGoodPacketCounterInterrupt.Value && txGoodPacketCounterInterruptEnable.Value) || 290 (txGoodByteCounterInterrupt.Value && txGoodByteCounterInterruptEnable.Value) || 291 (txBroadcastPacketCounterInterrupt.Value && txBroadcastPacketCounterInterruptEnable.Value) || 292 (txMulticastPacketCounterInterrupt.Value && txMulticastPacketCounterInterruptEnable.Value) || 293 (txUnicastPacketCounterInterrupt.Value && txUnicastPacketCounterInterruptEnable.Value) || 294 (txPacketCounterInterrupt.Value && txPacketCounterInterruptEnable.Value) || 295 (txByteCounterInterrupt.Value && txByteCounterInterruptEnable.Value); 296 297 private bool MMCRxInterruptStatus => 298 (rxFifoPacketCounterInterrupt.Value && rxFifoPacketCounterInterruptEnable.Value) || 299 (rxUnicastPacketCounterInterrupt.Value && rxUnicastPacketCounterInterruptEnable.Value) || 300 (rxCrcErrorPacketCounterInterrupt.Value && rxCrcErrorPacketCounterInterruptEnable.Value) || 301 (rxMulticastPacketCounterInterrupt.Value && rxMulticastPacketCounterInterruptEnable.Value) || 302 (rxBroadcastPacketCounterInterrupt.Value && rxBroadcastPacketCounterInterruptEnable.Value) || 303 (rxGoodByteCounterInterrupt.Value && rxGoodByteCounterInterruptEnable.Value) || 304 (rxByteCounterInterrupt.Value && rxByteCounterInterruptEnable.Value) || 305 (rxPacketCounterInterrupt.Value && rxPacketCounterInterruptEnable.Value); 306 307 private const ulong CounterMaxValue = UInt32.MaxValue; 308 private const int RxWatchdogDivider = 256; 309 private const uint EtherTypeMinimalValue = 0x600; 310 311 // This value may be increased if required, but some changes in register creation may be required 312 private const int MaxDMAChannels = 3; 313 } 314 } 315