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 8 using Antmicro.Migrant; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Peripherals.UART; 14 using Antmicro.Renode.Time; 15 using System; 16 using System.Collections.Generic; 17 using System.Linq; 18 19 namespace Antmicro.Renode.Peripherals.SCI 20 { 21 public class RenesasRZG_SCIFA : BasicWordPeripheral, IBytePeripheral, IUART, IHasFrequency, IKnownSize, INumberedGPIOOutput 22 { RenesasRZG_SCIFA(IMachine machine, long frequency)23 public RenesasRZG_SCIFA(IMachine machine, long frequency): base(machine) 24 { 25 Frequency = frequency; 26 27 Connections = Enumerable 28 .Range(0, NrOfInterrupts) 29 .ToDictionary<int, int, IGPIO>(idx => idx, _ => new GPIO()); 30 31 DefineRegisters(); 32 Reset(); 33 } 34 Reset()35 public override void Reset() 36 { 37 base.Reset(); 38 parityBit = Parity.Even; 39 receiveQueue.Clear(); 40 UpdateInterrupts(); 41 } 42 43 // Most registers are 16 bit wide, but some are 8 bit. 44 // The shorter ones are artificially extended to 16 bits (WithIgnoredBits). 45 // We don't use translation to prevent valueProviderCallback from being triggered during writes. ReadByte(long offset)46 public byte ReadByte(long offset) 47 { 48 switch((Registers)offset) 49 { 50 case Registers.BitRate: // ModulationDuty 51 case Registers.FifoDataReceive: 52 case Registers.FifoDataTransmit: 53 case Registers.SerialExtendedMode: 54 return (byte)RegistersCollection.Read(offset); 55 default: 56 this.ErrorLog( 57 "Trying to read byte from word register at offset 0x{0:X}. Returning 0x0", 58 offset 59 ); 60 return 0; 61 } 62 } 63 WriteByte(long offset, byte value)64 public void WriteByte(long offset, byte value) 65 { 66 switch((Registers)offset) 67 { 68 case Registers.BitRate: // ModulationDuty 69 case Registers.FifoDataReceive: 70 case Registers.FifoDataTransmit: 71 case Registers.SerialExtendedMode: 72 RegistersCollection.Write(offset, (ushort)value); 73 break; 74 default: 75 this.ErrorLog( 76 "Trying to write byte 0x{0:X} to word register at offset 0x{1:X}. Register won't be updated", 77 value, 78 offset 79 ); 80 break; 81 } 82 } 83 WriteChar(byte value)84 public void WriteChar(byte value) 85 { 86 if(!receiveEnabled.Value) 87 { 88 this.ErrorLog("Receiver is not enabled, dropping byte: 0x{0:x}", value); 89 return; 90 } 91 receiveQueue.Enqueue(value); 92 if(receiveQueue.Count > 0 && receiveQueue.Count < ReceiveFIFOTriggerCount) 93 { 94 receiveDataReady.Value = true; 95 } 96 if(receiveQueue.Count >= ReceiveFIFOTriggerCount) 97 { 98 receiveFifoFull.Value = true; 99 } 100 UpdateInterrupts(); 101 } 102 103 public long Size => 0x400; 104 105 // IRQs are bundled into 5 signals per channel in the following order: 106 // 0: ERI - Receive error 107 // 1: BRI - Break detection or overrun 108 // 2: RXI - Receive FIFO data full 109 // 3: TXI - Transmit FIFO data empty 110 // 4: TEI_DRI - Transmit end / Receive data ready 111 public IReadOnlyDictionary<int, IGPIO> Connections { get; } 112 113 public Bits StopBits => hasTwoStopBits.Value ? Bits.Two : Bits.One; 114 115 public Parity ParityBit => parityEnabled.Value ? parityBit : Parity.None; 116 117 public uint BaudRate 118 { 119 get 120 { 121 // We can't perform a shift if the exponent is negative 122 var n = clockSource.Value == 0 ? 123 0.5 : 1UL << (2 * (ushort)clockSource.Value - 1); 124 125 var prefix = 64UL; 126 if(doubleSpeedMode.Value) 127 { 128 prefix /= 2; 129 } 130 if(asynchronousBaseClock8Times.Value) 131 { 132 prefix /= 2; 133 } 134 135 return (uint)((Frequency * Math.Pow(10, 6)) / (prefix * n * bitRate.Value)) - 1; 136 } 137 } 138 139 public long Frequency { get; set; } 140 141 [field: Transient] 142 public event Action<byte> CharReceived; 143 DefineRegisters()144 private void DefineRegisters() 145 { 146 Registers.SerialMode.Define(this) 147 .WithValueField(0, 2, out clockSource, name: "CKS") 148 .WithReservedBits(2, 1) 149 .WithFlag(3, out hasTwoStopBits, name: "STOP") 150 .WithFlag(4, name: "PM", 151 valueProviderCallback: _ => parityBit == Parity.Odd, 152 writeCallback: (_, value) => parityBit = value ? Parity.Odd : Parity.Even) 153 .WithFlag(5, out parityEnabled, name: "PE") 154 .WithTaggedFlag("CHR", 6) // Character length, might be 8 or 7 bit 155 .WithEnumField(7, 1, out communicationMode, 156 writeCallback: (_, val) => 157 { 158 if(val == CommunicationMode.ClockSynchronous) 159 { 160 this.ErrorLog( 161 "{0} is not yet supported. Switching to {1}", 162 nameof(CommunicationMode.ClockSynchronous), 163 nameof(CommunicationMode.Asynchronous) 164 ); 165 communicationMode.Value = CommunicationMode.Asynchronous; 166 } 167 }, 168 name: "CM") 169 .WithReservedBits(8, 8); 170 171 Registers.BitRate.DefineConditional(this, () => registerSelect.Value == ModulationDutyRegisterSelect.BitRate, 0xff) 172 .WithValueField(0, 8, out bitRate, 173 writeCallback: (oldVal, newVal) => bitRate.Value = (!transmitEnabled.Value && !receiveEnabled.Value) ? newVal : oldVal, 174 name: "BRR") 175 .WithIgnoredBits(8, 8); 176 177 // Conditional, exclusive with BitRate 178 Registers.ModulationDuty.DefineConditional(this, () => registerSelect.Value == ModulationDutyRegisterSelect.ModulationDuty, 0xff) 179 .WithTag("MDDR", 0, 8) 180 .WithIgnoredBits(8, 8); 181 182 Registers.SerialControl.Define(this) 183 .WithTag("CKE", 0, 2) 184 .WithFlag(2, out transmitEndInterruptEnabled, name: "TEIE") 185 .WithTaggedFlag("REIE", 3) 186 .WithFlag(4, out receiveEnabled, name: "RE") 187 .WithFlag(5, out transmitEnabled, name: "TE", 188 changeCallback: (_, value) => 189 { 190 if(!value) 191 { 192 transmitFIFOEmpty.Value = true; 193 } 194 }) 195 .WithFlag(6, out receiveInterruptEnabled, name: "RIE") 196 .WithFlag(7, out transmitInterruptEnabled, name: "TIE", 197 // We always have empty transmit FIFO 198 changeCallback: (_, __) => transmitFIFOEmpty.Value = true) 199 .WithReservedBits(8, 8) 200 .WithChangeCallback((_, __) => UpdateInterrupts()); 201 202 Registers.FifoDataReceive.Define(this) 203 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => 204 { 205 if(receiveQueue.Count == 0) 206 { 207 this.WarningLog("Trying to read from an empty receive FIFO, returning 0x0."); 208 return 0; 209 } 210 var ret = receiveQueue.Dequeue(); 211 receiveFifoFull.Value = false; 212 if(receiveQueue.Count == 0) 213 { 214 receiveDataReady.Value = false; 215 } 216 UpdateInterrupts(); 217 return ret; 218 }, 219 name: "FRDR") 220 .WithIgnoredBits(8, 8); 221 222 Registers.FifoDataTransmit.Define(this) 223 .WithValueField(0, 8, FieldMode.Write, writeCallback: (_, val) => 224 { 225 if(!transmitEnabled.Value) 226 { 227 this.ErrorLog("Transmitter is not enabled, dropping byte: 0x{0:x}", (byte)val); 228 return; 229 } 230 CharReceived?.Invoke((byte)val); 231 // RZ/G2L Group, RZ/G2LC Group User's Manual: Hardware, states that 232 // TDFE and TEND flags are cleared when data is written to FTDR register. 233 // But TDFE is set again when quantity of data written FTDR is less than 234 // specified threshold, and TEND is set when FTDR becomes empty. 235 // Both actions take some time on real hardware, but happen immediately in Renode. 236 // Hence we use delay to prevent interrupts from being triggered too soon. 237 transmitFIFOEmpty.Value = false; 238 transmitEnd.Value = false; 239 UpdateInterrupts(); 240 machine.ScheduleAction(TimeInterval.FromMicroseconds(TransmitInterruptDelay), ___ => 241 { 242 transmitFIFOEmpty.Value = true; 243 transmitEnd.Value = true; 244 UpdateInterrupts(); 245 }); 246 }, 247 name: "FTDR") 248 .WithIgnoredBits(8, 8); 249 250 // According to the documentation this register should have a reset value of 0x20. 251 // Some software expects the TEND flag to be set even before transmitting the first character. 252 // Error status flags are modeled as fields to reduce the amount of logs generated during the simulation. 253 Registers.SerialStatus.Define(this, 0x60) 254 .WithFlag(0, out receiveDataReady, FieldMode.Read | FieldMode.WriteZeroToClear, name: "DR") 255 .WithFlag(1, out receiveFifoFull, FieldMode.Read | FieldMode.WriteZeroToClear, name: "RDF") 256 .WithFlag(2, FieldMode.Read | FieldMode.WriteZeroToClear, name: "PER") 257 .WithFlag(3, FieldMode.Read | FieldMode.WriteZeroToClear, name: "FER") 258 .WithFlag(4, FieldMode.Read | FieldMode.WriteZeroToClear, name: "BRK") 259 .WithFlag(5, out transmitFIFOEmpty, FieldMode.Read | FieldMode.WriteZeroToClear, name: "TDFE") 260 .WithFlag(6, out transmitEnd, FieldMode.Read | FieldMode.WriteZeroToClear, name: "TEND") 261 .WithFlag(7, FieldMode.Read | FieldMode.WriteZeroToClear, name: "ER") 262 .WithReservedBits(8, 8) 263 .WithWriteCallback((_, __) => UpdateInterrupts()); 264 265 Registers.FifoControl.Define(this) 266 .WithTaggedFlag("LOOP", 0) 267 .WithFlag(1, FieldMode.Read | FieldMode.WriteOneToClear, name: "RFRST", writeCallback: (_, __) => receiveQueue.Clear()) 268 .WithTaggedFlag("TFRST", 2) 269 .WithTaggedFlag("MCE", 3) 270 .WithTag("TTRG", 4, 2) 271 .WithValueField(6, 2, out receiveFifoDataTriggerNumberSelect, name: "RTRG") 272 .WithTag("RSTRG", 8, 3) 273 .WithReservedBits(11, 5) 274 .WithWriteCallback((_, __) => UpdateInterrupts()); 275 276 Registers.FifoDataCount.Define(this) 277 .WithValueField(0, 5, FieldMode.Read, name: "R", 278 valueProviderCallback: _ => (ulong)receiveQueue.Count >= MaxFIFOSize ? MaxFIFOSize : (ulong)receiveQueue.Count) 279 .WithReservedBits(5, 3) 280 // Transmission is instantaneous, so it will always be empty 281 .WithValueField(8, 5, name: "T", valueProviderCallback: _ => 0x0) 282 .WithReservedBits(13, 3); 283 284 Registers.SerialPort.Define(this) 285 .WithTaggedFlag("SPB2DT", 0) 286 .WithTaggedFlag("SPB2IO", 1) 287 .WithTaggedFlag("SCKDT", 2) 288 .WithTaggedFlag("SCKIO", 3) 289 .WithTaggedFlag("CTS2DT", 4) 290 .WithTaggedFlag("CTS2IO", 5) 291 .WithTaggedFlag("RTS2DT", 6) 292 .WithTaggedFlag("RTS2IO", 7) 293 .WithReservedBits(8, 8); 294 295 Registers.LineStatus.Define(this) 296 .WithTaggedFlag("ORER", 0) 297 .WithReservedBits(1, 1) 298 // We don't model parity errors 299 .WithTag("FER", 2, 5) 300 .WithReservedBits(7, 1) 301 .WithTag("PER", 8, 5) 302 .WithReservedBits(13, 3); 303 304 Registers.SerialExtendedMode.Define(this) 305 .WithFlag(0, out asynchronousBaseClock8Times, name: "ABCS0") 306 .WithReservedBits(1, 1) 307 .WithTaggedFlag("NFEN", 2) 308 .WithTaggedFlag("DIR", 3) 309 .WithEnumField(4, 1, out registerSelect, name: "MDDRS") 310 .WithTaggedFlag("BRME", 5) 311 .WithReservedBits(6, 1) 312 .WithFlag(7, out doubleSpeedMode, name: "BGDM") 313 .WithIgnoredBits(8, 8); 314 315 // We don't update interrupts here as docs don't specify that we should do it. 316 // They seem to indicate that interrupt should only be triggered when FIFO count changes. 317 // From RZ/G2L Group, RZ/G2LC Group User's Manual: Hardware, chapter 22: 318 // "When the quantity of transmit data written in the FTDR register as a result of transmission 319 // is equal to or less than the specified transmission trigger number ... interrupt request is generated" 320 // or 321 // "When the number of entries in the reception FIFO ... rises to or above the specified trigger number for reception, 322 // the RDF flag is set to 1 and a receive FIFO data full interrupt (RXI) request is generated" 323 Registers.FifoTriggerControl.Define(this, 0x1f1f) 324 .WithTag("TFTC", 0, 5) 325 .WithReservedBits(5, 2) 326 .WithTaggedFlag("TTRGS", 7) 327 .WithValueField(8, 5, out receiveFifoDataTriggerNumber, name: "RFTC") 328 .WithReservedBits(13, 2) 329 .WithFlag(15, out receiveTriggerSelect, name: "RTRGS"); 330 } 331 332 private int ReceiveFIFOTriggerCount 333 { 334 get 335 { 336 if(receiveTriggerSelect.Value) 337 { 338 return (int)receiveFifoDataTriggerNumber.Value; 339 } 340 else 341 { 342 switch(receiveFifoDataTriggerNumberSelect.Value) 343 { 344 case 0: 345 return 1; 346 case 1: 347 return 4; 348 case 2: 349 return 8; 350 case 3: 351 return 14; 352 default: 353 this.ErrorLog( 354 "{0} has invalid value {1}. Defaulting to 0x1.", 355 nameof(receiveFifoDataTriggerNumberSelect), 356 receiveFifoDataTriggerNumberSelect.Value 357 ); 358 return 1; 359 } 360 } 361 } 362 } 363 UpdateInterrupts()364 private void UpdateInterrupts() 365 { 366 Connections[ReceiveFifoFullIrqIdx].Set(receiveInterruptEnabled.Value && receiveFifoFull.Value); 367 // Transmit is always instant, so if the transmit interrupt is enabled 368 // and we have written some char, the IRQ triggers. 369 Connections[TransmitFifoEmptyIrqIdx].Set(transmitInterruptEnabled.Value && transmitFIFOEmpty.Value); 370 Connections[TransmitEndReceiveReadyIrqIdx].Set((receiveInterruptEnabled.Value && receiveDataReady.Value) || 371 (transmitEndInterruptEnabled.Value && transmitEnd.Value)); 372 // We don't implement these interrupts 373 Connections[ReceiveErrorIrqIdx].Set(false); 374 Connections[BreakOrOverrunIrqIdx].Set(false); 375 } 376 377 private Parity parityBit; 378 379 private IFlagRegisterField hasTwoStopBits; 380 private IFlagRegisterField parityEnabled; 381 private IFlagRegisterField doubleSpeedMode; 382 private IFlagRegisterField transmitEnabled; 383 private IFlagRegisterField transmitEndInterruptEnabled; 384 private IFlagRegisterField receiveEnabled; 385 private IFlagRegisterField receiveInterruptEnabled; 386 private IFlagRegisterField transmitInterruptEnabled; 387 private IFlagRegisterField transmitFIFOEmpty; 388 private IFlagRegisterField transmitEnd; 389 private IFlagRegisterField receiveDataReady; 390 private IFlagRegisterField receiveFifoFull; 391 private IValueRegisterField bitRate; 392 private IValueRegisterField clockSource; 393 private IValueRegisterField receiveFifoDataTriggerNumber; 394 private IFlagRegisterField receiveTriggerSelect; 395 private IValueRegisterField receiveFifoDataTriggerNumberSelect; 396 private IFlagRegisterField asynchronousBaseClock8Times; 397 private IEnumRegisterField<ModulationDutyRegisterSelect> registerSelect; 398 private IEnumRegisterField<CommunicationMode> communicationMode; 399 400 private readonly Queue<byte> receiveQueue = new Queue<byte>(); 401 402 private const int MaxFIFOSize = 16; 403 private const int NrOfInterrupts = 5; 404 private const int ReceiveErrorIrqIdx = 0; 405 private const int BreakOrOverrunIrqIdx = 1; 406 private const int ReceiveFifoFullIrqIdx = 2; 407 private const int TransmitFifoEmptyIrqIdx = 3; 408 private const int TransmitEndReceiveReadyIrqIdx = 4; 409 private const int TransmitInterruptDelay = 5; 410 411 private enum CommunicationMode 412 { 413 Asynchronous = 0, 414 ClockSynchronous = 1, 415 } 416 417 private enum ModulationDutyRegisterSelect 418 { 419 BitRate, 420 ModulationDuty 421 } 422 423 private enum Registers 424 { 425 SerialMode = 0x0, // SMR 426 // BitRate and ModulationDuty exist at the same address 427 // but are switchable at runtime via SEMR.MDDRS 428 BitRate = 0x2, // BRR 429 ModulationDuty = 0x2, // MDDR 430 SerialControl = 0x4, // SCR 431 FifoDataTransmit = 0x6, // FTDR 432 SerialStatus = 0x8, // FSR 433 FifoDataReceive = 0xA, // FRDR 434 FifoControl = 0xC, // FCR 435 FifoDataCount = 0xE, // FDR 436 SerialPort = 0x10, // SPTR 437 LineStatus = 0x12, // LSR 438 SerialExtendedMode = 0x14, // SEMR 439 FifoTriggerControl = 0x16, // FTCR 440 } 441 } 442 } 443