1 // 2 // Copyright (c) 2010-2025 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.Text; 10 using System.IO; 11 using Antmicro.Renode.Exceptions; 12 using Antmicro.Renode.Logging; 13 using Antmicro.Renode.Utilities; 14 using Antmicro.Renode.Utilities.Binding; 15 16 namespace Antmicro.Renode.Peripherals.CPU 17 { 18 public abstract partial class TranslationCPU 19 { 20 public bool EnableOpcodesCounting 21 { 22 set 23 { 24 TlibEnableOpcodesCounting(value ? 1 : 0u); 25 } 26 } 27 InstallOpcodeCounterPattern(string name, string pattern)28 public void InstallOpcodeCounterPattern(string name, string pattern) 29 { 30 if(pattern.Length != 16 && pattern.Length != 32) 31 { 32 throw new RecoverableException("Currently only 16 and 32-bit opcode patterns are supported"); 33 } 34 35 // no need to check the result value, as we have checked 36 // the pattern length already 37 Misc.TryParseBitPattern(pattern, out var opcode, out var mask); 38 39 InstallOpcodeCounterPattern(name, opcode, mask); 40 } 41 InstallOpcodeCounterPattern(string name, ulong opcode, ulong mask)42 public void InstallOpcodeCounterPattern(string name, ulong opcode, ulong mask) 43 { 44 if(opcodesMap.ContainsKey(name)) 45 { 46 throw new RecoverableException($"Opcode '{name}' already registered"); 47 } 48 49 var id = TlibInstallOpcodeCounter(opcode, mask); 50 if(id == 0) 51 { 52 throw new RecoverableException("Could not install opcode counter pattern"); 53 } 54 55 opcodesMap[name] = id; 56 this.Log(LogLevel.Debug, "Registered counter for opcode: {0}", name); 57 } 58 GetOpcodeCounter(string name)59 public ulong GetOpcodeCounter(string name) 60 { 61 if(!opcodesMap.TryGetValue(name, out var id)) 62 { 63 throw new RecoverableException($"Couldn't find the {name} opcode"); 64 } 65 return TlibGetOpcodeCounter(id); 66 } 67 GetAllOpcodesCounters()68 public string[,] GetAllOpcodesCounters() 69 { 70 return new Table() 71 .AddRow("Opcode", "Count") 72 .AddRows(opcodesMap, 73 x => x.Key, 74 x => TlibGetOpcodeCounter(x.Value).ToString()).ToArray(); 75 } 76 SaveAllOpcodesCounters(string path)77 public void SaveAllOpcodesCounters(string path) 78 { 79 using(var outputFile = new StreamWriter(path)) 80 { 81 foreach(var x in opcodesMap) 82 { 83 outputFile.WriteLine(string.Format("{0};{1}", x.Key, TlibGetOpcodeCounter(x.Value))); 84 } 85 } 86 } 87 ResetOpcodesCounters()88 public void ResetOpcodesCounters() 89 { 90 TlibResetOpcodeCounters(); 91 } 92 93 private readonly Dictionary<string, uint> opcodesMap = new Dictionary<string, uint>(); 94 95 #pragma warning disable 649 96 97 [Import] 98 private Action<uint> TlibEnableOpcodesCounting; 99 100 [Import] 101 private Func<uint, ulong> TlibGetOpcodeCounter; 102 103 [Import] 104 private Func<ulong, ulong, uint> TlibInstallOpcodeCounter; 105 106 [Import] 107 private Action TlibResetOpcodeCounters; 108 109 #pragma warning restore 649 110 } 111 } 112 113