1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System; 9 using System.Linq; 10 using System.Collections.Generic; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Core.Structure; 13 14 namespace Antmicro.Renode.Peripherals.CPU 15 { 16 // A few helper methods to simplify the common operations on all cpus in the cluster. 17 public static class ClusterExtensions 18 { SetPC(this Cluster cluster, ulong value)19 public static void SetPC(this Cluster cluster, ulong value) 20 { 21 foreach (var cpu in cluster.Clustered) 22 { 23 cpu.PC = value; 24 } 25 } 26 } 27 28 /// <summary> 29 /// <see cref="Cluster"/> could be a generic class to accept any types derived from <see cref="ICPU"/>, 30 /// but we wouldn't be able to use it in the platform description file (REPL), so it has a concrete type. 31 /// </summary> 32 public class Cluster : IPeripheralRegister<ICluster<TranslationCPU>, NullRegistrationPoint>, IPeripheralRegister<TranslationCPU, NullRegistrationPoint>, ICluster<TranslationCPU>, IHaltable 33 { Cluster(IMachine machine)34 public Cluster(IMachine machine) 35 { 36 this.machine = machine; 37 } 38 Reset()39 public void Reset() 40 { 41 foreach(var clustered in Clustered) 42 { 43 clustered.Reset(); 44 } 45 } 46 Register(ICluster<TranslationCPU> cluster, NullRegistrationPoint registrationPoint)47 public void Register(ICluster<TranslationCPU> cluster, NullRegistrationPoint registrationPoint) 48 { 49 // Intermediate clusters are registered only in the parent cluster, 50 // so they can be accessed through the cluster's tree hierarchy. 51 machine.RegisterAsAChildOf(this, cluster, NullRegistrationPoint.Instance); 52 clusters.Add(cluster); 53 } 54 Unregister(ICluster<TranslationCPU> cluster)55 public void Unregister(ICluster<TranslationCPU> cluster) 56 { 57 machine.UnregisterAsAChildOf(this, cluster); 58 clusters.Remove(cluster); 59 } 60 Register(TranslationCPU cpu, NullRegistrationPoint registrationPoint)61 public void Register(TranslationCPU cpu, NullRegistrationPoint registrationPoint) 62 { 63 // CPUs are registered both on sysbus and in the parent cluster, 64 // so they can be accessed either directly or through the cluster's tree hierarchy. 65 machine.RegisterAsAChildOf(this, cpu, NullRegistrationPoint.Instance); 66 machine.SystemBus.Register(cpu, new CPURegistrationPoint()); 67 cpus.Add(cpu); 68 } 69 Unregister(TranslationCPU cpu)70 public void Unregister(TranslationCPU cpu) 71 { 72 machine.UnregisterAsAChildOf(this, cpu); 73 machine.SystemBus.Unregister(cpu); 74 cpus.Remove(cpu); 75 } 76 77 public bool IsHalted 78 { 79 set 80 { 81 foreach(var cpu in this.Clustered) 82 { 83 cpu.IsHalted = value; 84 } 85 } 86 } 87 88 89 public IEnumerable<ICluster<TranslationCPU>> Clusters => clusters; 90 91 public IEnumerable<TranslationCPU> Clustered => cpus.Concat(clusters.SelectMany(cluster => cluster.Clustered)); 92 93 private readonly List<ICluster<TranslationCPU>> clusters = new List<ICluster<TranslationCPU>>(); 94 private readonly List<TranslationCPU> cpus = new List<TranslationCPU>(); 95 96 private readonly IMachine machine; 97 } 98 } 99