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.Linq; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Peripherals; 12 13 namespace Antmicro.Renode.RobotFramework 14 { 15 internal abstract class TestersProvider<TTester, TPeripheral> 16 where TPeripheral: class, IEmulationElement 17 where TTester: class 18 { TestersProvider()19 public TestersProvider() 20 { 21 testers = new Dictionary<int, TTester>(); 22 peripheralsWithTesters = new List<TPeripheral>(); 23 EmulationManager.Instance.EmulationChanged += () => 24 { 25 lock(testers) 26 { 27 testers.Clear(); 28 peripheralsWithTesters.Clear(); 29 } 30 }; 31 } 32 TryGetDefaultMachineOrThrowKeywordException(string peripheralName = null)33 public static IMachine TryGetDefaultMachineOrThrowKeywordException(string peripheralName = null) 34 { 35 if(!EmulationManager.Instance.CurrentEmulation.Machines.Any()) 36 { 37 string response = "There is no machine in the emulation."; 38 if(String.IsNullOrEmpty(peripheralName)) 39 { 40 throw new KeywordException(response); 41 } 42 else 43 { 44 throw new KeywordException(response + " Could not create tester for peripheral: {0}", peripheralName); 45 } 46 } 47 var machineObject = EmulationManager.Instance.CurrentEmulation.MachinesCount == 1 48 ? EmulationManager.Instance.CurrentEmulation.Machines.First() 49 : null; 50 if(machineObject == null) 51 { 52 throw new KeywordException("No machine name provided. Don't know which one to choose. Available machines: [{0}]", 53 string.Join(", ", EmulationManager.Instance.CurrentEmulation.Names)); 54 } 55 return machineObject; 56 } 57 CreateNewTester(Func<TPeripheral, TTester> creator, string peripheralOrExternalName, string machine = null)58 public int CreateNewTester(Func<TPeripheral, TTester> creator, string peripheralOrExternalName, string machine = null) 59 { 60 lock(testers) 61 { 62 TPeripheral emulationElement = null; 63 IMachine machineObject = null; 64 // first check if `peripheralOrExternalName` is not an external, then try match it to a peripheral 65 if(!EmulationManager.Instance.CurrentEmulation.ExternalsManager.TryGetByName<TPeripheral>(peripheralOrExternalName, out emulationElement)) 66 { 67 if(machine == null) 68 { 69 machineObject = TryGetDefaultMachineOrThrowKeywordException(peripheralOrExternalName); 70 } 71 else if(!EmulationManager.Instance.CurrentEmulation.TryGetMachineByName(machine, out machineObject)) 72 { 73 throw new KeywordException("Machine with name {0} not found. Available machines: [{1}]", machine, 74 string.Join(", ", EmulationManager.Instance.CurrentEmulation.Machines.Select(x => EmulationManager.Instance.CurrentEmulation[x]))); 75 } 76 77 if(!machineObject.TryGetByName(peripheralOrExternalName, out IPeripheral typeLessPeripheral)) 78 { 79 throw new KeywordException("Peripheral for machine '{0}' not found or of wrong type: '{1}'. Available peripherals: [{2}]", machine, peripheralOrExternalName, 80 string.Join(", ", machineObject.GetAllNames())); 81 } 82 83 emulationElement = typeLessPeripheral as TPeripheral; 84 if(emulationElement == null) 85 { 86 throw new KeywordException("Peripheral for machine '{0}' not found or of wrong type: '{1}'. Available peripherals: [{2}]", machine, peripheralOrExternalName, 87 string.Join(", ", machineObject.GetAllNames())); 88 } 89 } 90 91 var testerId = peripheralsWithTesters.IndexOf(emulationElement); 92 if(testerId != -1) 93 { 94 return testerId; 95 } 96 97 var tester = creator(emulationElement); 98 peripheralsWithTesters.Add(emulationElement); 99 testers.Add(peripheralsWithTesters.Count - 1, tester); 100 101 return peripheralsWithTesters.Count - 1; 102 } 103 } 104 SetDefaultTesterId(int? id)105 public void SetDefaultTesterId(int? id) 106 { 107 lock(testers) 108 { 109 if(id.HasValue) 110 { 111 if(!testers.TryGetValue(id.Value, out var tester)) 112 { 113 throw new KeywordException($"Tester #{id.Value} was not found. Create a tester before setting it as default"); 114 } 115 defaultTester = tester; 116 } 117 else 118 { 119 defaultTester = null; 120 } 121 } 122 } 123 GetTesterOrThrowException(int? testerId)124 protected TTester GetTesterOrThrowException(int? testerId) 125 { 126 lock(testers) 127 { 128 if(testerId == null) 129 { 130 if(defaultTester != null) 131 { 132 return defaultTester; 133 } 134 135 if(testers.Count != 1) 136 { 137 throw new KeywordException(testers.Count == 0 138 ? "There are no testers available." 139 : "There is more than one tester available - please specify ID of the desired tester."); 140 } 141 return testers.Single().Value; 142 } 143 144 if(!testers.TryGetValue(testerId.Value, out var tester)) 145 { 146 throw new KeywordException("Tester for given ID={0} was not found. Did you forget to create the tester?", testerId); 147 } 148 return tester; 149 } 150 } 151 152 private TTester defaultTester; 153 private readonly Dictionary<int, TTester> testers; 154 private readonly List<TPeripheral> peripheralsWithTesters; 155 } 156 } 157