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