1 //
2 // Copyright (c) 2010-2024 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.Peripherals.Bus;
9 using Antmicro.Renode.Core.Structure.Registers;
10 using Antmicro.Renode.Core;
11 
12 namespace Antmicro.Renode.Peripherals.UART
13 {
14     // This peripheral only has byte-wide registers, but we define it as a double-word peripheral and
15     // translate byte->dword instead of dword->byte to avoid unhandled read warnings on dword access.
16     [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)]
17     public class MiV_CoreUART : UARTBase, IDoubleWordPeripheral, IKnownSize
18     {
MiV_CoreUART(IMachine machine, ulong clockFrequency)19         public MiV_CoreUART(IMachine machine, ulong clockFrequency) : base(machine)
20         {
21             this.clockFrequency = clockFrequency;
22             var registersMap = new Dictionary<long, ByteRegister>
23             {
24                 {(long)Registers.TransmitData, new ByteRegister(this)
25                     .WithValueField(0, 8, FieldMode.Write, writeCallback: (_, b) => {
26                         this.TransmitCharacter((byte)b);
27                     })},
28 
29                 {(long)Registers.ReceiveData, new ByteRegister(this)
30                     .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => {
31                         this.TryGetCharacter(out var character);
32                         return character;
33                     })},
34 
35                 {(long)Registers.Control1, new ByteRegister(this)
36                     .WithValueField(0, 8, out baudValue0to7, name: "BAUD_VALUE_0_7")},
37 
38                 {(long)Registers.Control2, new ByteRegister(this)
39                     .WithFlag(0, name: "BIT8") // The register only provides a read-back function
40                     .WithFlag(1, out parityFlagField, name: "PARITY_EN")
41                     .WithFlag(2, out oddNEventFlagField, name: "ODD_N_EVEN")
42                     .WithValueField(3, 5, out baudValue8to12, name: "BAUD_VALUE_8_12")},
43 
44                 {(long)Registers.Control3, new ByteRegister(this)
45                     .WithValueField(0, 3, out baudValueFractionField, name: "BAUD_VAL_FRACTION")
46                     // bits 7:3 not mentioned in the documentation
47                 },
48 
49                 {(long)Registers.Status, new ByteRegister(this)
50                     .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => true, name: "TXRDY")
51                     .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => Count > 0, name: "RXRDY")
52                     .WithFlag(2, FieldMode.Read, name: "PARITY_ERR")
53                     .WithFlag(3, FieldMode.Read, name: "OVERFLOW")
54                     .WithFlag(4, FieldMode.Read, name: "FRAMING_ERROR")}
55                     // bits 7:5 not used according to the documentation
56             };
57 
58             registers = new ByteRegisterCollection(this, registersMap);
59         }
60 
Reset()61         public override void Reset()
62         {
63             base.Reset();
64             registers.Reset();
65         }
66 
ReadDoubleWord(long offset)67         public uint ReadDoubleWord(long offset)
68         {
69             return registers.Read(offset);
70         }
71 
WriteDoubleWord(long offset, uint value)72         public void WriteDoubleWord(long offset, uint value)
73         {
74             registers.Write(offset, (byte)value);
75         }
76 
77         public long Size => 0x18;
78 
79         public override Bits StopBits => Bits.One;
80 
81         public override Parity ParityBit => parityFlagField.Value ? (oddNEventFlagField.Value ? Parity.Odd : Parity.Even) : Parity.None;
82 
83         public override uint BaudRate => (uint)((clockFrequency / (16 * ((baudValue8to12.Value << 8) + baudValue0to7.Value + 1))) + baudValueFractionField.Value * 0.125);
84 
CharWritten()85         protected override void CharWritten()
86         {
87             // intentionally left blank
88         }
89 
QueueEmptied()90         protected override void QueueEmptied()
91         {
92             // intentionally left blank
93         }
94 
95         private readonly IValueRegisterField baudValue0to7;
96         private readonly IFlagRegisterField parityFlagField;
97         private readonly IFlagRegisterField oddNEventFlagField;
98         private readonly IValueRegisterField baudValue8to12;
99         private readonly IValueRegisterField baudValueFractionField;
100         private readonly ByteRegisterCollection registers;
101         private readonly ulong clockFrequency;
102 
103         private enum Registers : long
104         {
105             TransmitData = 0x0,
106             ReceiveData = 0x04,
107             Control1 = 0x08,
108             Control2 = 0x0C,
109             Status = 0x10,
110             Control3 = 0x14
111         }
112     }
113 }
114