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;
8 using System.Collections.Generic;
9 using System.Linq;
10 using Antmicro.Migrant;
11 using Antmicro.Renode.Core;
12 using Antmicro.Renode.Core.Structure;
13 using Antmicro.Renode.Peripherals.Bus;
14 using Antmicro.Renode.Peripherals.CPU;
15 
16 namespace Antmicro.Renode.Peripherals.UART
17 {
18     public static class VirtualConsoleExtensions
19     {
CreateVirtualConsole(this IMachine machine, string name)20         public static void CreateVirtualConsole(this IMachine machine, string name)
21         {
22             var virtConsole = new VirtualConsole(machine);
23             machine.RegisterAsAChildOf(machine.SystemBus, virtConsole, NullRegistrationPoint.Instance);
24             machine.SetLocalName(virtConsole, name);
25         }
26     }
27 
28     public class VirtualConsole : IUART
29     {
VirtualConsole(IMachine machine)30         public VirtualConsole(IMachine machine)
31         {
32             bus = machine.SystemBus;
33             fifo = new Queue<byte>();
34             locker = new object();
35         }
36 
Reset()37         public void Reset()
38         {
39             Clear();
40         }
41 
Clear()42         public void Clear()
43         {
44             lock(locker)
45             {
46                 fifo.Clear();
47             }
48         }
49 
IsEmpty()50         public bool IsEmpty()
51         {
52             lock(locker)
53             {
54                 return fifo.Count == 0;
55             }
56         }
57 
Contains(byte value)58         public bool Contains(byte value)
59         {
60             lock(locker)
61             {
62                 return fifo.Contains(value);
63             }
64         }
65 
WriteChar(byte value)66         public void WriteChar(byte value)
67         {
68             lock(locker)
69             {
70                 fifo.Enqueue(value);
71                 CharWritten?.Invoke(value);
72             }
73             if(Echo)
74             {
75                 DisplayChar(value);
76             }
77         }
78 
ReadBuffer(int maxCount = 1)79         public byte[] ReadBuffer(int maxCount = 1)
80         {
81             lock(locker)
82             {
83                 return GetFifoIterator().Take(maxCount).ToArray();
84             }
85         }
86 
GetBuffer()87         public byte[] GetBuffer()
88         {
89             lock(locker)
90             {
91                 return fifo.ToArray();
92             }
93         }
94 
WriteBufferToMemory(ulong address, int maxCount, ICPU context = null)95         public long WriteBufferToMemory(ulong address, int maxCount, ICPU context = null)
96         {
97             var buffer = ReadBuffer(maxCount);
98             bus.WriteBytes(buffer, address, true, context);
99             return buffer.Length;
100         }
101 
DisplayChar(byte value)102         public void DisplayChar(byte value)
103         {
104             CharReceived?.Invoke(value);
105         }
106 
107         public bool Echo { get; set; } = true;
108 
109         public uint BaudRate { get; set; }
110         public Bits StopBits { get; set; }
111         public Parity ParityBit { get; set; }
112 
113         [field: Transient]
114         public event Action<byte> CharReceived;
115 
116         [field: Transient]
117         public event Action<byte> CharWritten;
118 
GetFifoIterator()119         private IEnumerable<byte> GetFifoIterator()
120         {
121             while(fifo.Count > 0)
122             {
123                 yield return fifo.Dequeue();
124             }
125         }
126 
127         private readonly IBusController bus;
128         private readonly object locker;
129         private readonly Queue<byte> fifo;
130     }
131 }
132