~mmach/netext73/mesa_2004

« back to all changes in this revision

Viewing changes to src/intel/common/intel_l3_config.c

  • Committer: mmach
  • Date: 2022-09-22 20:00:35 UTC
  • Revision ID: netbit73@gmail.com-20220922200035-j2mt0pv92d002zy3
2022-09-22 21:17:58

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2015 Intel Corporation
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
21
 * IN THE SOFTWARE.
 
22
 */
 
23
 
 
24
#include <stdlib.h>
 
25
#include <math.h>
 
26
 
 
27
#include "util/macros.h"
 
28
 
 
29
#include "intel_l3_config.h"
 
30
 
 
31
struct intel_l3_list {
 
32
   const struct intel_l3_config *configs;
 
33
   int length;
 
34
};
 
35
 
 
36
#define DECLARE_L3_LIST(hw) \
 
37
   struct intel_l3_list hw##_l3_list = \
 
38
   { .configs = hw##_l3_configs, .length = ARRAY_SIZE(hw##_l3_configs) }
 
39
 
 
40
/**
 
41
 * IVB/HSW validated L3 configurations.  The first entry will be used as
 
42
 * default by gfx7_restore_default_l3_config(), otherwise the ordering is
 
43
 * unimportant.
 
44
 */
 
45
static const struct intel_l3_config ivb_l3_configs[] = {
 
46
   /* SLM URB ALL DC  RO  IS   C   T */
 
47
   {{  0, 32,  0,  0, 32,  0,  0,  0 }},
 
48
   {{  0, 32,  0, 16, 16,  0,  0,  0 }},
 
49
   {{  0, 32,  0,  4,  0,  8,  4, 16 }},
 
50
   {{  0, 28,  0,  8,  0,  8,  4, 16 }},
 
51
   {{  0, 28,  0, 16,  0,  8,  4,  8 }},
 
52
   {{  0, 28,  0,  8,  0, 16,  4,  8 }},
 
53
   {{  0, 28,  0,  0,  0, 16,  4, 16 }},
 
54
   {{  0, 32,  0,  0,  0, 16,  0, 16 }},
 
55
   {{  0, 28,  0,  4, 32,  0,  0,  0 }},
 
56
   {{ 16, 16,  0, 16, 16,  0,  0,  0 }},
 
57
   {{ 16, 16,  0,  8,  0,  8,  8,  8 }},
 
58
   {{ 16, 16,  0,  4,  0,  8,  4, 16 }},
 
59
   {{ 16, 16,  0,  4,  0, 16,  4,  8 }},
 
60
   {{ 16, 16,  0,  0, 32,  0,  0,  0 }},
 
61
};
 
62
DECLARE_L3_LIST(ivb);
 
63
 
 
64
/**
 
65
 * VLV validated L3 configurations.  \sa ivb_l3_configs.
 
66
 */
 
67
static const struct intel_l3_config vlv_l3_configs[] = {
 
68
   /* SLM URB ALL DC  RO  IS   C   T */
 
69
   {{  0, 64,  0,  0, 32,  0,  0,  0 }},
 
70
   {{  0, 80,  0,  0, 16,  0,  0,  0 }},
 
71
   {{  0, 80,  0,  8,  8,  0,  0,  0 }},
 
72
   {{  0, 64,  0, 16, 16,  0,  0,  0 }},
 
73
   {{  0, 60,  0,  4, 32,  0,  0,  0 }},
 
74
   {{ 32, 32,  0, 16, 16,  0,  0,  0 }},
 
75
   {{ 32, 40,  0,  8, 16,  0,  0,  0 }},
 
76
   {{ 32, 40,  0, 16,  8,  0,  0,  0 }},
 
77
};
 
78
DECLARE_L3_LIST(vlv);
 
79
 
 
80
/**
 
81
 * BDW validated L3 configurations.  \sa ivb_l3_configs.
 
82
 */
 
83
static const struct intel_l3_config bdw_l3_configs[] = {
 
84
   /* SLM URB ALL DC  RO  IS   C   T */
 
85
   {{  0, 48, 48,  0,  0,  0,  0,  0 }},
 
86
   {{  0, 48,  0, 16, 32,  0,  0,  0 }},
 
87
   {{  0, 32,  0, 16, 48,  0,  0,  0 }},
 
88
   {{  0, 32,  0,  0, 64,  0,  0,  0 }},
 
89
   {{  0, 32, 64,  0,  0,  0,  0,  0 }},
 
90
   {{ 24, 16, 48,  0,  0,  0,  0,  0 }},
 
91
   {{ 24, 16,  0, 16, 32,  0,  0,  0 }},
 
92
   {{ 24, 16,  0, 32, 16,  0,  0,  0 }},
 
93
};
 
94
DECLARE_L3_LIST(bdw);
 
95
 
 
96
/**
 
97
 * CHV/SKL validated L3 configurations.  \sa ivb_l3_configs.
 
98
 */
 
99
static const struct intel_l3_config chv_l3_configs[] = {
 
100
   /* SLM URB ALL DC  RO  IS   C   T */
 
101
   {{  0, 48, 48,  0,  0,  0,  0,  0 }},
 
102
   {{  0, 48,  0, 16, 32,  0,  0,  0 }},
 
103
   {{  0, 32,  0, 16, 48,  0,  0,  0 }},
 
104
   {{  0, 32,  0,  0, 64,  0,  0,  0 }},
 
105
   {{  0, 32, 64,  0,  0,  0,  0,  0 }},
 
106
   {{ 32, 16, 48,  0,  0,  0,  0,  0 }},
 
107
   {{ 32, 16,  0, 16, 32,  0,  0,  0 }},
 
108
   {{ 32, 16,  0, 32, 16,  0,  0,  0 }},
 
109
};
 
110
DECLARE_L3_LIST(chv);
 
111
 
 
112
/**
 
113
 * BXT 2x6 validated L3 configurations.  \sa ivb_l3_configs.
 
114
 */
 
115
static const struct intel_l3_config bxt_2x6_l3_configs[] = {
 
116
   /* SLM URB ALL DC  RO  IS   C   T */
 
117
   {{  0, 32, 48,  0,  0,  0,  0,  0 }},
 
118
   {{  0, 32,  0,  8, 40,  0,  0,  0 }},
 
119
   {{  0, 32,  0, 32, 16,  0,  0,  0 }},
 
120
   {{ 16, 16, 48,  0,  0,  0,  0,  0 }},
 
121
   {{ 16, 16,  0, 40,  8,  0,  0,  0 }},
 
122
   {{ 16, 16,  0, 16, 32,  0,  0,  0 }},
 
123
};
 
124
DECLARE_L3_LIST(bxt_2x6);
 
125
 
 
126
/**
 
127
 * ICL validated L3 configurations.  \sa icl_l3_configs.
 
128
 * Zeroth entry in below table has been commented out intentionally
 
129
 * due to known issues with this configuration. Many other entries
 
130
 * suggested by h/w specification aren't added here because they
 
131
 * do under allocation of L3 cache with below partitioning.
 
132
 */
 
133
static const struct intel_l3_config icl_l3_configs[] = {
 
134
   /* SLM URB ALL DC  RO  IS   C   T */
 
135
   /*{{  0, 16, 80,  0,  0,  0,  0,  0 }},*/
 
136
   {{  0, 32, 64,  0,  0,  0,  0,  0 }},
 
137
};
 
138
DECLARE_L3_LIST(icl);
 
139
 
 
140
/**
 
141
 * TGL validated L3 configurations.  \sa tgl_l3_configs.
 
142
 */
 
143
static const struct intel_l3_config tgl_l3_configs[] = {
 
144
   /* SLM URB ALL DC  RO  IS   C   T */
 
145
   {{  0, 32,  88,  0,  0,  0,  0,  0 }},
 
146
   {{  0, 16, 104,  0,  0,  0,  0,  0 }},
 
147
};
 
148
DECLARE_L3_LIST(tgl);
 
149
 
 
150
/**
 
151
 * Empty L3 configurations.  \sa empty_l3_configs.
 
152
 */
 
153
static const struct intel_l3_config empty_l3_configs[] = {
 
154
   /* No configurations. L3FullWayAllocationEnable is always set. */
 
155
};
 
156
DECLARE_L3_LIST(empty);
 
157
 
 
158
/**
 
159
 * Return a zero-terminated array of validated L3 configurations for the
 
160
 * specified device.
 
161
 */
 
162
static const struct intel_l3_list *
 
163
get_l3_list(const struct intel_device_info *devinfo)
 
164
{
 
165
   switch (devinfo->ver) {
 
166
   case 7:
 
167
      return (devinfo->platform == INTEL_PLATFORM_BYT ? &vlv_l3_list : &ivb_l3_list);
 
168
 
 
169
   case 8:
 
170
      return (devinfo->platform == INTEL_PLATFORM_CHV ? &chv_l3_list : &bdw_l3_list);
 
171
 
 
172
   case 9:
 
173
      if (devinfo->l3_banks == 1)
 
174
         return &bxt_2x6_l3_list;
 
175
      return &chv_l3_list;
 
176
 
 
177
   case 11:
 
178
      return &icl_l3_list;
 
179
 
 
180
   case 12:
 
181
      if (devinfo->platform == INTEL_PLATFORM_DG1 ||
 
182
          intel_device_info_is_dg2(devinfo))
 
183
         return &empty_l3_list;
 
184
      else
 
185
         return &tgl_l3_list;
 
186
 
 
187
   default:
 
188
      unreachable("Not implemented");
 
189
   }
 
190
}
 
191
 
 
192
/**
 
193
 * L1-normalize a vector of L3 partition weights.
 
194
 */
 
195
static struct intel_l3_weights
 
196
norm_l3_weights(struct intel_l3_weights w)
 
197
{
 
198
   float sz = 0;
 
199
 
 
200
   for (unsigned i = 0; i < INTEL_NUM_L3P; i++)
 
201
      sz += w.w[i];
 
202
 
 
203
   for (unsigned i = 0; i < INTEL_NUM_L3P; i++)
 
204
      w.w[i] /= sz;
 
205
 
 
206
   return w;
 
207
}
 
208
 
 
209
/**
 
210
 * Get the relative partition weights of the specified L3 configuration.
 
211
 */
 
212
struct intel_l3_weights
 
213
intel_get_l3_config_weights(const struct intel_l3_config *cfg)
 
214
{
 
215
   if (cfg) {
 
216
      struct intel_l3_weights w;
 
217
 
 
218
      for (unsigned i = 0; i < INTEL_NUM_L3P; i++)
 
219
         w.w[i] = cfg->n[i];
 
220
 
 
221
      return norm_l3_weights(w);
 
222
   } else {
 
223
      const struct intel_l3_weights w = { { 0 } };
 
224
      return w;
 
225
   }
 
226
}
 
227
 
 
228
/**
 
229
 * Distance between two L3 configurations represented as vectors of weights.
 
230
 * Usually just the L1 metric except when the two configurations are
 
231
 * considered incompatible in which case the distance will be infinite.  Note
 
232
 * that the compatibility condition is asymmetric -- They will be considered
 
233
 * incompatible whenever the reference configuration \p w0 requires SLM, DC,
 
234
 * or URB but \p w1 doesn't provide it.
 
235
 */
 
236
float
 
237
intel_diff_l3_weights(struct intel_l3_weights w0, struct intel_l3_weights w1)
 
238
{
 
239
   if ((w0.w[INTEL_L3P_SLM] && !w1.w[INTEL_L3P_SLM]) ||
 
240
       (w0.w[INTEL_L3P_DC] && !w1.w[INTEL_L3P_DC] && !w1.w[INTEL_L3P_ALL]) ||
 
241
       (w0.w[INTEL_L3P_URB] && !w1.w[INTEL_L3P_URB])) {
 
242
      return HUGE_VALF;
 
243
 
 
244
   } else {
 
245
      float dw = 0;
 
246
 
 
247
      for (unsigned i = 0; i < INTEL_NUM_L3P; i++)
 
248
         dw += fabsf(w0.w[i] - w1.w[i]);
 
249
 
 
250
      return dw;
 
251
   }
 
252
}
 
253
 
 
254
/**
 
255
 * Return a reasonable default L3 configuration for the specified device based
 
256
 * on whether SLM and DC are required.  In the non-SLM non-DC case the result
 
257
 * is intended to approximately resemble the hardware defaults.
 
258
 */
 
259
struct intel_l3_weights
 
260
intel_get_default_l3_weights(const struct intel_device_info *devinfo,
 
261
                             bool needs_dc, bool needs_slm)
 
262
{
 
263
   struct intel_l3_weights w = {{ 0 }};
 
264
 
 
265
   w.w[INTEL_L3P_SLM] = devinfo->ver < 11 && needs_slm;
 
266
   w.w[INTEL_L3P_URB] = 1.0;
 
267
 
 
268
   if (devinfo->ver >= 8) {
 
269
      w.w[INTEL_L3P_ALL] = 1.0;
 
270
   } else {
 
271
      w.w[INTEL_L3P_DC] = needs_dc ? 0.1 : 0;
 
272
      w.w[INTEL_L3P_RO] = devinfo->platform == INTEL_PLATFORM_BYT ? 0.5 : 1.0;
 
273
   }
 
274
 
 
275
   return norm_l3_weights(w);
 
276
}
 
277
 
 
278
/**
 
279
 * Get the default L3 configuration
 
280
 */
 
281
const struct intel_l3_config *
 
282
intel_get_default_l3_config(const struct intel_device_info *devinfo)
 
283
{
 
284
   /* For efficiency assume that the first entry of the array matches the
 
285
    * default configuration.
 
286
    */
 
287
   const struct intel_l3_list *const list = get_l3_list(devinfo);
 
288
   assert(list->length > 0 || devinfo->ver >= 12);
 
289
   if (list->length > 0) {
 
290
      const struct intel_l3_config *const cfg = &list->configs[0];
 
291
      assert(cfg == intel_get_l3_config(devinfo,
 
292
                       intel_get_default_l3_weights(devinfo, false, false)));
 
293
      return cfg;
 
294
   } else {
 
295
      return NULL;
 
296
   }
 
297
}
 
298
 
 
299
/**
 
300
 * Return the closest validated L3 configuration for the specified device and
 
301
 * weight vector.
 
302
 */
 
303
const struct intel_l3_config *
 
304
intel_get_l3_config(const struct intel_device_info *devinfo,
 
305
                    struct intel_l3_weights w0)
 
306
{
 
307
   const struct intel_l3_list *const list = get_l3_list(devinfo);
 
308
   const struct intel_l3_config *const cfgs = list->configs;
 
309
   const struct intel_l3_config *cfg_best = NULL;
 
310
   float dw_best = HUGE_VALF;
 
311
 
 
312
   for (int i = 0; i < list->length; i++) {
 
313
      const struct intel_l3_config *cfg = &cfgs[i];
 
314
      const float dw = intel_diff_l3_weights(w0, intel_get_l3_config_weights(cfg));
 
315
 
 
316
      if (dw < dw_best) {
 
317
         cfg_best = cfg;
 
318
         dw_best = dw;
 
319
      }
 
320
   }
 
321
 
 
322
   assert(cfg_best || devinfo->ver >= 12);
 
323
   return cfg_best;
 
324
}
 
325
 
 
326
/**
 
327
 * Return the size of an L3 way in KB.
 
328
 */
 
329
static unsigned
 
330
get_l3_way_size(const struct intel_device_info *devinfo)
 
331
{
 
332
   const unsigned way_size_per_bank =
 
333
      (devinfo->ver >= 9 && devinfo->l3_banks == 1) || devinfo->ver >= 11 ?
 
334
      4 : 2;
 
335
 
 
336
   assert(devinfo->l3_banks);
 
337
   return way_size_per_bank * devinfo->l3_banks;
 
338
}
 
339
 
 
340
/**
 
341
 * Return the unit brw_context::urb::size is expressed in, in KB.  \sa
 
342
 * intel_device_info::urb::size.
 
343
 */
 
344
static unsigned
 
345
get_urb_size_scale(const struct intel_device_info *devinfo)
 
346
{
 
347
   return (devinfo->ver >= 8 ? devinfo->num_slices : 1);
 
348
}
 
349
 
 
350
unsigned
 
351
intel_get_l3_config_urb_size(const struct intel_device_info *devinfo,
 
352
                             const struct intel_l3_config *cfg)
 
353
{
 
354
   /* We don't have to program the URB size for some platforms. It's a fixed
 
355
    * value.
 
356
    */
 
357
   if (cfg == NULL) {
 
358
      ASSERTED const struct intel_l3_list *const list = get_l3_list(devinfo);
 
359
      assert(list->length == 0);
 
360
      return devinfo->urb.size;
 
361
   }
 
362
 
 
363
   /* From the SKL "L3 Allocation and Programming" documentation:
 
364
    *
 
365
    * "URB is limited to 1008KB due to programming restrictions.  This is not
 
366
    * a restriction of the L3 implementation, but of the FF and other clients.
 
367
    * Therefore, in a GT4 implementation it is possible for the programmed
 
368
    * allocation of the L3 data array to provide 3*384KB=1152KB for URB, but
 
369
    * only 1008KB of this will be used."
 
370
    */
 
371
   const unsigned max = (devinfo->ver == 9 ? 1008 : ~0);
 
372
   return MIN2(max, cfg->n[INTEL_L3P_URB] * get_l3_way_size(devinfo)) /
 
373
          get_urb_size_scale(devinfo);
 
374
}
 
375
 
 
376
/**
 
377
 * Print out the specified L3 configuration.
 
378
 */
 
379
void
 
380
intel_dump_l3_config(const struct intel_l3_config *cfg, FILE *fp)
 
381
{
 
382
   fprintf(stderr, "SLM=%d URB=%d ALL=%d DC=%d RO=%d IS=%d C=%d T=%d\n",
 
383
           cfg->n[INTEL_L3P_SLM], cfg->n[INTEL_L3P_URB], cfg->n[INTEL_L3P_ALL],
 
384
           cfg->n[INTEL_L3P_DC], cfg->n[INTEL_L3P_RO],
 
385
           cfg->n[INTEL_L3P_IS], cfg->n[INTEL_L3P_C], cfg->n[INTEL_L3P_T]);
 
386
}