14d14968f6d322633d3977e76981a337983cc66e3florian#include <stdio.h>
24d14968f6d322633d3977e76981a337983cc66e3florian#include <assert.h>
34d14968f6d322633d3977e76981a337983cc66e3florian#include <stdint.h>
44d14968f6d322633d3977e76981a337983cc66e3florian#include <inttypes.h>
54d14968f6d322633d3977e76981a337983cc66e3florian#include "opcodes.h"
64d14968f6d322633d3977e76981a337983cc66e3florian
74d14968f6d322633d3977e76981a337983cc66e3florianuint64_t
84d14968f6d322633d3977e76981a337983cc66e3florianecag(int ai, int li, int ti)
94d14968f6d322633d3977e76981a337983cc66e3florian{
104d14968f6d322633d3977e76981a337983cc66e3florian   register uint64_t result asm("2") = 0;
114d14968f6d322633d3977e76981a337983cc66e3florian   register uint64_t input  asm("3") = (ai << 4) | (li << 1) | ti;
124d14968f6d322633d3977e76981a337983cc66e3florian
134d14968f6d322633d3977e76981a337983cc66e3florian   asm volatile( ECAG(2,0,3,000,00)
144d14968f6d322633d3977e76981a337983cc66e3florian                 : "=d" (result) : "d" (input));
154d14968f6d322633d3977e76981a337983cc66e3florian   return result;
164d14968f6d322633d3977e76981a337983cc66e3florian}
174d14968f6d322633d3977e76981a337983cc66e3florian
184d14968f6d322633d3977e76981a337983cc66e3florianstatic unsigned
194d14968f6d322633d3977e76981a337983cc66e3florianget_level_info(uint64_t topology, unsigned level)
204d14968f6d322633d3977e76981a337983cc66e3florian{
214d14968f6d322633d3977e76981a337983cc66e3florian   return (topology >> (56 - level * 8)) & 0xff;
224d14968f6d322633d3977e76981a337983cc66e3florian}
234d14968f6d322633d3977e76981a337983cc66e3florian
244d14968f6d322633d3977e76981a337983cc66e3florianint
254d14968f6d322633d3977e76981a337983cc66e3florianmain(void)
264d14968f6d322633d3977e76981a337983cc66e3florian{
274d14968f6d322633d3977e76981a337983cc66e3florian   unsigned level;
284d14968f6d322633d3977e76981a337983cc66e3florian   uint64_t topology;
294d14968f6d322633d3977e76981a337983cc66e3florian
304d14968f6d322633d3977e76981a337983cc66e3florian   topology = ecag(0, 0, 0);   // get summary
314d14968f6d322633d3977e76981a337983cc66e3florian
324d14968f6d322633d3977e76981a337983cc66e3florian   /* ECAG supports at most 8 levels of cache. Iterate over all of them
334d14968f6d322633d3977e76981a337983cc66e3florian      ignoring those not present. */
344d14968f6d322633d3977e76981a337983cc66e3florian   for (level = 0; level < 8; level++) {
354d14968f6d322633d3977e76981a337983cc66e3florian      unsigned info = get_level_info(topology, level);
364d14968f6d322633d3977e76981a337983cc66e3florian
374d14968f6d322633d3977e76981a337983cc66e3florian      if ((info & 0xc) == 0) continue;  // cache does not exist at this level
384d14968f6d322633d3977e76981a337983cc66e3florian
394d14968f6d322633d3977e76981a337983cc66e3florian      unsigned cache_type  =  info & 0x3;
404d14968f6d322633d3977e76981a337983cc66e3florian      unsigned cache_scope = (info & 0xc) >> 2;
414d14968f6d322633d3977e76981a337983cc66e3florian      char *type, *scope;
424d14968f6d322633d3977e76981a337983cc66e3florian
434d14968f6d322633d3977e76981a337983cc66e3florian      switch (cache_type) {
444d14968f6d322633d3977e76981a337983cc66e3florian      case 0: type = "separate data and instruction"; break;
454d14968f6d322633d3977e76981a337983cc66e3florian      case 1: type = "instruction"; break;
464d14968f6d322633d3977e76981a337983cc66e3florian      case 2: type = "data"; break;
474d14968f6d322633d3977e76981a337983cc66e3florian      case 3: type = "unified data and instruction"; break;
484d14968f6d322633d3977e76981a337983cc66e3florian      }
494d14968f6d322633d3977e76981a337983cc66e3florian
504d14968f6d322633d3977e76981a337983cc66e3florian      switch (cache_scope) {
514d14968f6d322633d3977e76981a337983cc66e3florian      case 0: assert(0);  // should never occur because cache exists
524d14968f6d322633d3977e76981a337983cc66e3florian      case 1: scope = "private";  break;
534d14968f6d322633d3977e76981a337983cc66e3florian      case 2: scope = "shared";   break;
544d14968f6d322633d3977e76981a337983cc66e3florian      case 3: scope = "reserved"; break;
554d14968f6d322633d3977e76981a337983cc66e3florian      }
564d14968f6d322633d3977e76981a337983cc66e3florian
574d14968f6d322633d3977e76981a337983cc66e3florian      printf("L%u topology: %s; %s\n", level+1, type, scope);
584d14968f6d322633d3977e76981a337983cc66e3florian      printf("L%u cache line size data: %"PRId64"\n", level+1,
594d14968f6d322633d3977e76981a337983cc66e3florian             ecag(1, level, 0));
604d14968f6d322633d3977e76981a337983cc66e3florian      printf("L%u cache line size insn: %"PRId64"\n", level+1,
614d14968f6d322633d3977e76981a337983cc66e3florian             ecag(1, level, 1));
624d14968f6d322633d3977e76981a337983cc66e3florian      printf("L%u total cachesize data: %"PRId64"\n", level+1,
634d14968f6d322633d3977e76981a337983cc66e3florian             ecag(2, level, 0));
644d14968f6d322633d3977e76981a337983cc66e3florian      printf("L%u total cachesize insn: %"PRId64"\n", level+1,
654d14968f6d322633d3977e76981a337983cc66e3florian             ecag(2, level, 1));
664d14968f6d322633d3977e76981a337983cc66e3florian      printf("L%u set. assoc.     data: %"PRId64"\n", level+1,
674d14968f6d322633d3977e76981a337983cc66e3florian             ecag(3, level, 0));
684d14968f6d322633d3977e76981a337983cc66e3florian      printf("L%u set. assoc.     insn: %"PRId64"\n", level+1,
694d14968f6d322633d3977e76981a337983cc66e3florian             ecag(3, level, 1));
704d14968f6d322633d3977e76981a337983cc66e3florian   }
714d14968f6d322633d3977e76981a337983cc66e3florian
724d14968f6d322633d3977e76981a337983cc66e3florian   return 0;
734d14968f6d322633d3977e76981a337983cc66e3florian}
74