1 // 2 // Copyright (c) 2010-2023 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.IO; 10 using System.Linq; 11 using System.Text; 12 using Antmicro.Renode.Debugging; 13 using Antmicro.Renode.Exceptions; 14 using Antmicro.Renode.Logging; 15 using Antmicro.Renode.Peripherals.Bus; 16 using Antmicro.Renode.Utilities.Binding; 17 18 namespace Antmicro.Renode.Peripherals.CPU.GuestProfiling.ProtoBuf 19 { 20 public class PerfettoTraceWriter 21 { PerfettoTraceWriter()22 public PerfettoTraceWriter() 23 { 24 trace = new Trace(); 25 } 26 CreateTrack(string name, ulong trackId, bool isCounterTrack = false)27 public void CreateTrack(string name, ulong trackId, bool isCounterTrack = false) 28 { 29 var track = new TrackDescriptor 30 { 31 Uuid = trackId, 32 Name = name 33 }; 34 35 if(isCounterTrack) 36 { 37 track.Counter = new TrackDescriptor.CounterDescriptor(); 38 } 39 40 trace.Packets.Add(new TracePacket 41 { 42 TrustedPacketSequenceId = SequenceId, 43 TrackDescriptor = track 44 }); 45 } 46 CreateEventBegin(ulong timestamp, string name, ulong trackId)47 public void CreateEventBegin(ulong timestamp, string name, ulong trackId) 48 { 49 trace.Packets.Add(new TracePacket 50 { 51 Timestamp = timestamp, 52 TrustedPacketSequenceId = SequenceId, 53 TrackEvent = new TrackEvent 54 { 55 Name = name, 56 TrackUuid = trackId, 57 type = TrackEvent.Type.TypeSliceBegin 58 } 59 }); 60 } 61 CreateEventEnd(ulong timestamp, ulong trackId)62 public void CreateEventEnd(ulong timestamp, ulong trackId) 63 { 64 trace.Packets.Add(new TracePacket 65 { 66 Timestamp = timestamp, 67 TrustedPacketSequenceId = SequenceId, 68 TrackEvent = new TrackEvent 69 { 70 TrackUuid = trackId, 71 type = TrackEvent.Type.TypeSliceEnd 72 } 73 }); 74 } 75 CreateEventInstant(ulong timestamp, string name, ulong trackId)76 public void CreateEventInstant(ulong timestamp, string name, ulong trackId) 77 { 78 trace.Packets.Add(new TracePacket 79 { 80 Timestamp = timestamp, 81 TrustedPacketSequenceId = SequenceId, 82 TrackEvent = new TrackEvent 83 { 84 Name = name, 85 TrackUuid = trackId, 86 type = TrackEvent.Type.TypeInstant 87 } 88 }); 89 } 90 CreateEventCounter(ulong timestamp, long value, ulong trackId)91 public void CreateEventCounter(ulong timestamp, long value, ulong trackId) 92 { 93 trace.Packets.Add(new TracePacket 94 { 95 Timestamp = timestamp, 96 TrustedPacketSequenceId = SequenceId, 97 TrackEvent = new TrackEvent 98 { 99 CounterValue = value, 100 TrackUuid = trackId, 101 type = TrackEvent.Type.TypeCounter 102 } 103 }); 104 } 105 CreateEventCounter(ulong timestamp, double value, ulong trackId)106 public void CreateEventCounter(ulong timestamp, double value, ulong trackId) 107 { 108 trace.Packets.Add(new TracePacket 109 { 110 Timestamp = timestamp, 111 TrustedPacketSequenceId = SequenceId, 112 TrackEvent = new TrackEvent 113 { 114 DoubleCounterValue = value, 115 TrackUuid = trackId, 116 type = TrackEvent.Type.TypeCounter 117 } 118 }); 119 } 120 FlushBuffer(Stream fileStream)121 public void FlushBuffer(Stream fileStream) 122 { 123 if(lastSyncMarker >= SyncMarkerInterval) 124 { 125 // Add a sync packet 126 trace.Packets.Add(new TracePacket 127 { 128 TrustedPacketSequenceId = SequenceId, 129 SynchronizationMarker = SyncMarkerBytes 130 }); 131 lastSyncMarker = 0; 132 } 133 134 global::ProtoBuf.Serializer.Serialize(fileStream, trace); 135 lastSyncMarker += (uint)PacketCount; 136 trace.Packets.Clear(); 137 } 138 RemoveLastNPackets(int packetCount)139 public void RemoveLastNPackets(int packetCount) 140 { 141 trace.Packets.RemoveRange(trace.Packets.Count - packetCount, packetCount); 142 } 143 144 public int PacketCount => trace.Packets.Count; 145 146 // Perfetto will look for this exact sequence when it is parsing a longer trace 147 // Emitting this sequence can be used to partition the trace, so Perfetto doesn't have to load everything at once 148 private static readonly byte[] SyncMarkerBytes = Guid.ParseExact("{82477a76-b28d-42ba-81dc-33326d57a079}", "B").ToByteArray(); 149 150 private readonly Trace trace; 151 private uint lastSyncMarker; 152 153 private const uint SequenceId = 0; 154 private const uint SyncMarkerInterval = 10000; 155 } 156 } 157