1 //
2 // Copyright (c) 2010-2024 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 using System;
9 using System.IO;
10 using Antmicro.Migrant;
11 using Antmicro.Migrant.Customization;
12 using Antmicro.Renode.Core;
13 using Antmicro.Renode.Peripherals.UART;
14 using System.Collections.Generic;
15 using Antmicro.Renode.Logging;
16 using Antmicro.Renode.Time;
17 
18 namespace Antmicro.Renode.EventRecording
19 {
20     [Transient]
21     public class Player : IDisposable
22     {
Player(FileStream stream, IMachine machine)23         public Player(FileStream stream, IMachine machine)
24         {
25             this.machine = machine;
26             this.stream = stream;
27             deserializer = new Serializer(new Settings(useBuffering: false, disableTypeStamping: true)).ObtainOpenStreamDeserializer(stream);
28             handlersCache = new Dictionary<NameAndHandler, Delegate>();
29             entries = deserializer.DeserializeMany<IRecordEntry>().GetEnumerator();
30             if(!entries.MoveNext())
31             {
32                 entries = null;
33             }
34         }
35 
Play(TimeInterval elapsedVirtualTime)36         public void Play(TimeInterval elapsedVirtualTime)
37         {
38             if(entries == null)
39             {
40                 return;
41             }
42             while(entries.Current.Timestamp <= elapsedVirtualTime)
43             {
44                 var entry = entries.Current;
45                 entry.Play(ResolveHandler);
46                 if(!entries.MoveNext())
47                 {
48                     entries = null;
49                     return;
50                 }
51             }
52         }
53 
Dispose()54         public void Dispose()
55         {
56             stream.Close();
57         }
58 
ResolveHandler(string name, Delegate nullifiedHandler)59         private Delegate ResolveHandler(string name, Delegate nullifiedHandler)
60         {
61             var nameAndHandler = new NameAndHandler(name, nullifiedHandler);
62             if(handlersCache.ContainsKey(nameAndHandler))
63             {
64                 return handlersCache[nameAndHandler];
65             }
66             var target = machine[name];
67             var result = Delegate.CreateDelegate(nullifiedHandler.GetType(), target, nullifiedHandler.Method);
68             handlersCache.Add(nameAndHandler, result);
69             return result;
70         }
71 
72         private IEnumerator<IRecordEntry> entries;
73         private readonly Serializer.OpenStreamDeserializer deserializer;
74         private readonly Dictionary<NameAndHandler, Delegate> handlersCache;
75         private readonly FileStream stream;
76         private readonly IMachine machine;
77 
78         private struct NameAndHandler
79         {
NameAndHandlerAntmicro.Renode.EventRecording.Player.NameAndHandler80             public NameAndHandler(string name, Delegate handler) : this()
81             {
82                 this.Name = name;
83                 this.Handler = handler;
84             }
85 
86             public string Name { get; private set; }
87             public Delegate Handler { get; private set; }
88 
EqualsAntmicro.Renode.EventRecording.Player.NameAndHandler89             public override bool Equals(object obj)
90             {
91                 if(obj == null)
92                 {
93                     return false;
94                 }
95                 if(obj.GetType() != typeof(NameAndHandler))
96                 {
97                     return false;
98                 }
99                 var other = (NameAndHandler)obj;
100                 return this == other;
101             }
102 
GetHashCodeAntmicro.Renode.EventRecording.Player.NameAndHandler103             public override int GetHashCode()
104             {
105                 unchecked
106                 {
107                     return (Name != null ? Name.GetHashCode() : 0) ^ (Handler != null ? Handler.GetHashCode() : 0);
108                 }
109             }
110 
operator ==Antmicro.Renode.EventRecording.Player.NameAndHandler111             public static bool operator==(NameAndHandler first, NameAndHandler second)
112             {
113                 return first.Name == second.Name && first.Handler == second.Handler;
114             }
115 
operator !=Antmicro.Renode.EventRecording.Player.NameAndHandler116             public static bool operator!=(NameAndHandler first, NameAndHandler second)
117             {
118                 return !(first == second);
119             }
120         }
121     }
122 }
123 
124