blob: 7782dfa67ff161455dde1849b0022247b35fb18c [file] [log] [blame]
Georgios Katsikas13ccba62020-03-18 12:05:03 +01001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.drivers.server.impl.devices;
18
19import org.onosproject.drivers.server.devices.cpu.BasicCpuCacheDevice;
20import org.onosproject.drivers.server.devices.cpu.CpuCacheHierarchyDevice;
21import org.onosproject.drivers.server.devices.cpu.CpuCacheId;
22import org.onosproject.drivers.server.devices.cpu.CpuCoreId;
23import org.onosproject.drivers.server.devices.cpu.CpuVendor;
24
25import com.google.common.base.MoreObjects;
26
27import java.util.HashMap;
28import java.util.Map;
29import java.util.Objects;
30
31import static com.google.common.base.Preconditions.checkNotNull;
32import static com.google.common.base.Preconditions.checkArgument;
33import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_CAPACITY_NEGATIVE;
34import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_CAPACITY_CORE_NEGATIVE;
35import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_CAPACITY_LLC_NEGATIVE;
36import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_CAPACITY_TOTAL_NEGATIVE;
37import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_HIERARCHY_NULL;
38import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_INSERTION_FAILED;
39import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_LEVELS_EXCEEDED;
40import static org.onosproject.drivers.server.Constants.MSG_CPU_CACHE_LEVELS_NEGATIVE;
41import static org.onosproject.drivers.server.Constants.MSG_CPU_CORES_NEGATIVE;
42import static org.onosproject.drivers.server.Constants.MSG_CPU_SOCKETS_NEGATIVE;
43import static org.onosproject.drivers.server.Constants.MSG_CPU_VENDOR_NULL;
44
45/**
46 * Default implementation for a CPU cache hierarchy.
47 */
48public final class DefaultCpuCacheHierarchyDevice implements CpuCacheHierarchyDevice {
49
50 private final CpuVendor vendor;
51 private final int socketsNb;
52 private final int coresNb;
53 private final int levels;
54 private final long perCoreCapacity;
55 private final long llcCapacity;
56 private final long totalCapacity;
57 private Map<CpuCacheId, BasicCpuCacheDevice> cacheHierarchy;
58
59 /**
60 * Maximum number of CPU cache levels.
61 */
62 public static final int MAX_CPU_CACHE_LEVELS = 4;
63
64 private DefaultCpuCacheHierarchyDevice(
65 CpuVendor vendor,
66 int socketsNb,
67 int coresNb,
68 int levels,
69 long perCoreCapacity,
70 long llcCapacity,
71 Map<CpuCacheId, BasicCpuCacheDevice> cacheHierarchy) {
72 checkNotNull(vendor, MSG_CPU_VENDOR_NULL);
73 checkArgument(socketsNb > 0, MSG_CPU_SOCKETS_NEGATIVE);
74 checkArgument((coresNb > 0) && (coresNb < CpuCoreId.MAX_CPU_CORE_NB),
75 MSG_CPU_CORES_NEGATIVE);
76 checkArgument((levels > 0) && (levels <= MAX_CPU_CACHE_LEVELS),
77 MSG_CPU_CACHE_LEVELS_NEGATIVE);
78 checkArgument(perCoreCapacity > 0, MSG_CPU_CACHE_CAPACITY_CORE_NEGATIVE);
79 checkArgument(llcCapacity > 0, MSG_CPU_CACHE_CAPACITY_LLC_NEGATIVE);
80 checkNotNull(cacheHierarchy, MSG_CPU_CACHE_HIERARCHY_NULL);
81
82 this.vendor = vendor;
83 this.socketsNb = socketsNb;
84 this.coresNb = coresNb;
85 this.levels = levels;
86 this.perCoreCapacity = perCoreCapacity;
87 this.llcCapacity = llcCapacity;
88
89 // The total capacity is the sum of the (shared) socket-level and the per-core capacities
90 this.totalCapacity = (socketsNb * llcCapacity) + (coresNb * perCoreCapacity);
91 checkArgument((this.totalCapacity > this.perCoreCapacity) &&
92 (this.totalCapacity > this.llcCapacity),
93 MSG_CPU_CACHE_CAPACITY_TOTAL_NEGATIVE);
94 this.cacheHierarchy = cacheHierarchy;
95 }
96
97 /**
98 * Creates a builder for DefaultCpuCacheHierarchyDevice object.
99 *
100 * @return builder object for DefaultCpuCacheHierarchyDevice object
101 */
102 public static DefaultCpuCacheHierarchyDevice.Builder builder() {
103 return new Builder();
104 }
105
106 @Override
107 public CpuVendor vendor() {
108 return this.vendor;
109 }
110
111 @Override
112 public int socketsNb() {
113 return this.socketsNb;
114 }
115
116 @Override
117 public int coresNb() {
118 return this.coresNb;
119 }
120
121 @Override
122 public int levels() {
123 return this.levels;
124 }
125
126 @Override
127 public long perCoreCapacity() {
128 return this.perCoreCapacity;
129 }
130
131 @Override
132 public long llcCapacity() {
133 return this.llcCapacity;
134 }
135
136 @Override
137 public long totalCapacity() {
138 return this.totalCapacity;
139 }
140
141 @Override
142 public Map<CpuCacheId, BasicCpuCacheDevice> cacheHierarchy() {
143 return cacheHierarchy;
144 }
145
146 @Override
147 public String toString() {
148 return MoreObjects.toStringHelper(this)
149 .omitNullValues()
150 .add("vendor", vendor())
151 .add("socketsNb", socketsNb())
152 .add("coresNb", coresNb())
153 .add("levels", levels())
154 .add("perCoreCapacity", perCoreCapacity())
155 .add("llcCapacity", llcCapacity())
156 .add("totalCapacity", totalCapacity())
157 .add("cacheHierarchy", cacheHierarchy())
158 .toString();
159 }
160
161 @Override
162 public boolean equals(Object obj) {
163 if (obj == this) {
164 return true;
165 }
166 if (!(obj instanceof CpuCacheHierarchyDevice)) {
167 return false;
168 }
169 CpuCacheHierarchyDevice device = (CpuCacheHierarchyDevice) obj;
170 return this.vendor() == device.vendor() &&
171 this.socketsNb() == device.socketsNb() &&
172 this.coresNb() == device.coresNb() &&
173 this.levels() == device.levels() &&
174 this.perCoreCapacity() == device.perCoreCapacity() &&
175 this.llcCapacity() == device.llcCapacity() &&
176 this.totalCapacity() == device.totalCapacity() &&
177 this.cacheHierarchy() == device.cacheHierarchy();
178 }
179
180 @Override
181 public int hashCode() {
182 return Objects.hash(vendor, socketsNb, coresNb, levels, perCoreCapacity,
183 llcCapacity, totalCapacity, cacheHierarchy);
184 }
185
186 public static final class Builder {
187
188 CpuVendor vendor = null;
189 int socketsNb = -1;
190 int coresNb = -1;
191 int levels = -1;
192 long perCoreCapacity = 0;
193 long llcCapacity = 0;
194 Map<CpuCacheId, BasicCpuCacheDevice> cacheHierarchy =
195 new HashMap<CpuCacheId, BasicCpuCacheDevice>();
196
197 private Builder() {
198
199 }
200
201 /**
202 * Sets the number of CPU sockets.
203 *
204 * @param socketsNb number of CPU sockets
205 * @return builder object
206 */
207 public Builder setSocketsNumber(int socketsNb) {
208 this.socketsNb = socketsNb;
209 return this;
210 }
211
212 /**
213 * Sets the number of CPU cores.
214 *
215 * @param coresNb number of CPU cores
216 * @return builder object
217 */
218 public Builder setCoresNumber(int coresNb) {
219 this.coresNb = coresNb;
220 return this;
221 }
222
223 /**
224 * Sets the number of CPU cache levels.
225 *
226 * @param levels number of CPU cache levels
227 * @return builder object
228 */
229 public Builder setLevels(int levels) {
230 this.levels = levels;
231 return this;
232 }
233
234 /**
235 * Add a basic CPU cache device into this hierarchy.
236 *
237 * @param cacheDev a new basic CPU cache device
238 * @return builder object
239 */
240 public Builder addBasicCpuCacheDevice(BasicCpuCacheDevice cacheDev) {
241 checkNotNull(cacheDev, "Basic CPU cache device is null");
242 int currentSize = this.cacheHierarchy.size();
243 this.cacheHierarchy.put(cacheDev.cacheId(), cacheDev);
244 checkArgument(this.cacheHierarchy.size() == currentSize + 1,
245 MSG_CPU_CACHE_INSERTION_FAILED);
246 checkArgument(this.cacheHierarchy.size() <= MAX_CPU_CACHE_LEVELS,
247 MSG_CPU_CACHE_LEVELS_EXCEEDED);
248
249 if (this.vendor == null) {
250 this.vendor = cacheDev.vendor();
251 }
252
253 long capacity = cacheDev.capacity();
254 checkArgument(capacity > 0, MSG_CPU_CACHE_CAPACITY_NEGATIVE);
255 if (cacheDev.isShared()) {
256 this.llcCapacity = capacity;
257 } else {
258 this.perCoreCapacity += capacity;
259 }
260
261 return this;
262 }
263
264 /**
265 * Creates a DefaultCpuCacheHierarchyDevice object.
266 *
267 * @return DefaultCpuCacheHierarchyDevice object
268 */
269 public DefaultCpuCacheHierarchyDevice build() {
270 return new DefaultCpuCacheHierarchyDevice(
271 vendor, socketsNb, coresNb, levels,
272 perCoreCapacity, llcCapacity, cacheHierarchy);
273 }
274
275 }
276
277}