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