Home | History | Annotate | Download | only in common
      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 #include "main/macros.h"
     29 
     30 #include "gen_l3_config.h"
     31 
     32 /**
     33  * IVB/HSW validated L3 configurations.  The first entry will be used as
     34  * default by gen7_restore_default_l3_config(), otherwise the ordering is
     35  * unimportant.
     36  */
     37 static const struct gen_l3_config ivb_l3_configs[] = {
     38    /* SLM URB ALL DC  RO  IS   C   T */
     39    {{  0, 32,  0,  0, 32,  0,  0,  0 }},
     40    {{  0, 32,  0, 16, 16,  0,  0,  0 }},
     41    {{  0, 32,  0,  4,  0,  8,  4, 16 }},
     42    {{  0, 28,  0,  8,  0,  8,  4, 16 }},
     43    {{  0, 28,  0, 16,  0,  8,  4,  8 }},
     44    {{  0, 28,  0,  8,  0, 16,  4,  8 }},
     45    {{  0, 28,  0,  0,  0, 16,  4, 16 }},
     46    {{  0, 32,  0,  0,  0, 16,  0, 16 }},
     47    {{  0, 28,  0,  4, 32,  0,  0,  0 }},
     48    {{ 16, 16,  0, 16, 16,  0,  0,  0 }},
     49    {{ 16, 16,  0,  8,  0,  8,  8,  8 }},
     50    {{ 16, 16,  0,  4,  0,  8,  4, 16 }},
     51    {{ 16, 16,  0,  4,  0, 16,  4,  8 }},
     52    {{ 16, 16,  0,  0, 32,  0,  0,  0 }},
     53    {{ 0 }}
     54 };
     55 
     56 /**
     57  * VLV validated L3 configurations.  \sa ivb_l3_configs.
     58  */
     59 static const struct gen_l3_config vlv_l3_configs[] = {
     60    /* SLM URB ALL DC  RO  IS   C   T */
     61    {{  0, 64,  0,  0, 32,  0,  0,  0 }},
     62    {{  0, 80,  0,  0, 16,  0,  0,  0 }},
     63    {{  0, 80,  0,  8,  8,  0,  0,  0 }},
     64    {{  0, 64,  0, 16, 16,  0,  0,  0 }},
     65    {{  0, 60,  0,  4, 32,  0,  0,  0 }},
     66    {{ 32, 32,  0, 16, 16,  0,  0,  0 }},
     67    {{ 32, 40,  0,  8, 16,  0,  0,  0 }},
     68    {{ 32, 40,  0, 16,  8,  0,  0,  0 }},
     69    {{ 0 }}
     70 };
     71 
     72 /**
     73  * BDW validated L3 configurations.  \sa ivb_l3_configs.
     74  */
     75 static const struct gen_l3_config bdw_l3_configs[] = {
     76    /* SLM URB ALL DC  RO  IS   C   T */
     77    {{  0, 48, 48,  0,  0,  0,  0,  0 }},
     78    {{  0, 48,  0, 16, 32,  0,  0,  0 }},
     79    {{  0, 32,  0, 16, 48,  0,  0,  0 }},
     80    {{  0, 32,  0,  0, 64,  0,  0,  0 }},
     81    {{  0, 32, 64,  0,  0,  0,  0,  0 }},
     82    {{ 24, 16, 48,  0,  0,  0,  0,  0 }},
     83    {{ 24, 16,  0, 16, 32,  0,  0,  0 }},
     84    {{ 24, 16,  0, 32, 16,  0,  0,  0 }},
     85    {{ 0 }}
     86 };
     87 
     88 /**
     89  * CHV/SKL validated L3 configurations.  \sa ivb_l3_configs.
     90  */
     91 static const struct gen_l3_config chv_l3_configs[] = {
     92    /* SLM URB ALL DC  RO  IS   C   T */
     93    {{  0, 48, 48,  0,  0,  0,  0,  0 }},
     94    {{  0, 48,  0, 16, 32,  0,  0,  0 }},
     95    {{  0, 32,  0, 16, 48,  0,  0,  0 }},
     96    {{  0, 32,  0,  0, 64,  0,  0,  0 }},
     97    {{  0, 32, 64,  0,  0,  0,  0,  0 }},
     98    {{ 32, 16, 48,  0,  0,  0,  0,  0 }},
     99    {{ 32, 16,  0, 16, 32,  0,  0,  0 }},
    100    {{ 32, 16,  0, 32, 16,  0,  0,  0 }},
    101    {{ 0 }}
    102 };
    103 
    104 /**
    105  * Return a zero-terminated array of validated L3 configurations for the
    106  * specified device.
    107  */
    108 static const struct gen_l3_config *
    109 get_l3_configs(const struct gen_device_info *devinfo)
    110 {
    111    switch (devinfo->gen) {
    112    case 7:
    113       return (devinfo->is_baytrail ? vlv_l3_configs : ivb_l3_configs);
    114 
    115    case 8:
    116       return (devinfo->is_cherryview ? chv_l3_configs : bdw_l3_configs);
    117 
    118    case 9:
    119       return chv_l3_configs;
    120 
    121    default:
    122       unreachable("Not implemented");
    123    }
    124 }
    125 
    126 /**
    127  * L1-normalize a vector of L3 partition weights.
    128  */
    129 static struct gen_l3_weights
    130 norm_l3_weights(struct gen_l3_weights w)
    131 {
    132    float sz = 0;
    133 
    134    for (unsigned i = 0; i < GEN_NUM_L3P; i++)
    135       sz += w.w[i];
    136 
    137    for (unsigned i = 0; i < GEN_NUM_L3P; i++)
    138       w.w[i] /= sz;
    139 
    140    return w;
    141 }
    142 
    143 /**
    144  * Get the relative partition weights of the specified L3 configuration.
    145  */
    146 struct gen_l3_weights
    147 gen_get_l3_config_weights(const struct gen_l3_config *cfg)
    148 {
    149    if (cfg) {
    150       struct gen_l3_weights w;
    151 
    152       for (unsigned i = 0; i < GEN_NUM_L3P; i++)
    153          w.w[i] = cfg->n[i];
    154 
    155       return norm_l3_weights(w);
    156    } else {
    157       const struct gen_l3_weights w = { { 0 } };
    158       return w;
    159    }
    160 }
    161 
    162 /**
    163  * Distance between two L3 configurations represented as vectors of weights.
    164  * Usually just the L1 metric except when the two configurations are
    165  * considered incompatible in which case the distance will be infinite.  Note
    166  * that the compatibility condition is asymmetric -- They will be considered
    167  * incompatible whenever the reference configuration \p w0 requires SLM, DC,
    168  * or URB but \p w1 doesn't provide it.
    169  */
    170 float
    171 gen_diff_l3_weights(struct gen_l3_weights w0, struct gen_l3_weights w1)
    172 {
    173    if ((w0.w[GEN_L3P_SLM] && !w1.w[GEN_L3P_SLM]) ||
    174        (w0.w[GEN_L3P_DC] && !w1.w[GEN_L3P_DC] && !w1.w[GEN_L3P_ALL]) ||
    175        (w0.w[GEN_L3P_URB] && !w1.w[GEN_L3P_URB])) {
    176       return HUGE_VALF;
    177 
    178    } else {
    179       float dw = 0;
    180 
    181       for (unsigned i = 0; i < GEN_NUM_L3P; i++)
    182          dw += fabs(w0.w[i] - w1.w[i]);
    183 
    184       return dw;
    185    }
    186 }
    187 
    188 /**
    189  * Return a reasonable default L3 configuration for the specified device based
    190  * on whether SLM and DC are required.  In the non-SLM non-DC case the result
    191  * is intended to approximately resemble the hardware defaults.
    192  */
    193 struct gen_l3_weights
    194 gen_get_default_l3_weights(const struct gen_device_info *devinfo,
    195                            bool needs_dc, bool needs_slm)
    196 {
    197    struct gen_l3_weights w = {{ 0 }};
    198 
    199    w.w[GEN_L3P_SLM] = needs_slm;
    200    w.w[GEN_L3P_URB] = 1.0;
    201 
    202    if (devinfo->gen >= 8) {
    203       w.w[GEN_L3P_ALL] = 1.0;
    204    } else {
    205       w.w[GEN_L3P_DC] = needs_dc ? 0.1 : 0;
    206       w.w[GEN_L3P_RO] = devinfo->is_baytrail ? 0.5 : 1.0;
    207    }
    208 
    209    return norm_l3_weights(w);
    210 }
    211 
    212 /**
    213  * Get the default L3 configuration
    214  */
    215 const struct gen_l3_config *
    216 gen_get_default_l3_config(const struct gen_device_info *devinfo)
    217 {
    218    /* For efficiency assume that the first entry of the array matches the
    219     * default configuration.
    220     */
    221    const struct gen_l3_config *const cfg = get_l3_configs(devinfo);
    222    assert(cfg == gen_get_l3_config(devinfo,
    223                     gen_get_default_l3_weights(devinfo, false, false)));
    224    return cfg;
    225 }
    226 
    227 /**
    228  * Return the closest validated L3 configuration for the specified device and
    229  * weight vector.
    230  */
    231 const struct gen_l3_config *
    232 gen_get_l3_config(const struct gen_device_info *devinfo,
    233                   struct gen_l3_weights w0)
    234 {
    235    const struct gen_l3_config *const cfgs = get_l3_configs(devinfo);
    236    const struct gen_l3_config *cfg_best = NULL;
    237    float dw_best = HUGE_VALF;
    238 
    239    for (const struct gen_l3_config *cfg = cfgs; cfg->n[GEN_L3P_URB]; cfg++) {
    240       const float dw = gen_diff_l3_weights(w0, gen_get_l3_config_weights(cfg));
    241 
    242       if (dw < dw_best) {
    243          cfg_best = cfg;
    244          dw_best = dw;
    245       }
    246    }
    247 
    248    return cfg_best;
    249 }
    250 
    251 /**
    252  * Return the size of an L3 way in KB.
    253  */
    254 static unsigned
    255 get_l3_way_size(const struct gen_device_info *devinfo)
    256 {
    257    if (devinfo->is_baytrail)
    258       return 2;
    259 
    260    else if (devinfo->gt == 1 ||
    261             devinfo->is_cherryview ||
    262             devinfo->is_broxton)
    263       return 4;
    264 
    265    else
    266       return 8 * devinfo->num_slices;
    267 }
    268 
    269 /**
    270  * Return the unit brw_context::urb::size is expressed in, in KB.  \sa
    271  * gen_device_info::urb::size.
    272  */
    273 static unsigned
    274 get_urb_size_scale(const struct gen_device_info *devinfo)
    275 {
    276    return (devinfo->gen >= 8 ? devinfo->num_slices : 1);
    277 }
    278 
    279 unsigned
    280 gen_get_l3_config_urb_size(const struct gen_device_info *devinfo,
    281                            const struct gen_l3_config *cfg)
    282 {
    283    /* From the SKL "L3 Allocation and Programming" documentation:
    284     *
    285     * "URB is limited to 1008KB due to programming restrictions.  This is not
    286     * a restriction of the L3 implementation, but of the FF and other clients.
    287     * Therefore, in a GT4 implementation it is possible for the programmed
    288     * allocation of the L3 data array to provide 3*384KB=1152KB for URB, but
    289     * only 1008KB of this will be used."
    290     */
    291    const unsigned max = (devinfo->gen == 9 ? 1008 : ~0);
    292    return MIN2(max, cfg->n[GEN_L3P_URB] * get_l3_way_size(devinfo)) /
    293           get_urb_size_scale(devinfo);
    294 }
    295 
    296 /**
    297  * Print out the specified L3 configuration.
    298  */
    299 void
    300 gen_dump_l3_config(const struct gen_l3_config *cfg, FILE *fp)
    301 {
    302    fprintf(stderr, "SLM=%d URB=%d ALL=%d DC=%d RO=%d IS=%d C=%d T=%d\n",
    303            cfg->n[GEN_L3P_SLM], cfg->n[GEN_L3P_URB], cfg->n[GEN_L3P_ALL],
    304            cfg->n[GEN_L3P_DC], cfg->n[GEN_L3P_RO],
    305            cfg->n[GEN_L3P_IS], cfg->n[GEN_L3P_C], cfg->n[GEN_L3P_T]);
    306 }
    307