/* Copyright (C) 2009 Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING3. If not see . */ /* { dg-do run } */ /* { dg-require-effective-target "ealib" } */ #include #include #include #include #ifdef __EA64__ #define addr unsigned long long #else #define addr unsigned long #endif static __ea void *bigblock; static __ea void *block; static int *ls_block; extern char __cache_tag_array_size[]; #define CACHE_SIZE (4 * (int) &__cache_tag_array_size[0]) #define LINE_SIZE ((addr)128) void init_mem (void) { bigblock = malloc_ea (CACHE_SIZE + 2 * LINE_SIZE); block = malloc_ea (2 * LINE_SIZE); ls_block = malloc (LINE_SIZE); memset_ea (bigblock, 0, CACHE_SIZE + 2 * LINE_SIZE); memset_ea (block, -1, 2 * LINE_SIZE); memset (ls_block, -1, LINE_SIZE); cache_flush (); } /* Test 1: Simple cache fetching. */ void test1 (void) { addr aligned = ((((addr) block) + LINE_SIZE - 1) & -LINE_SIZE); int *p1 = NULL; int *p2 = NULL; int i = 0; /* First, check if the same addr give the same cache ptr. */ p1 = cache_fetch ((__ea void *) aligned); p2 = cache_fetch ((__ea void *) aligned); if (p1 != p2) abort (); /* Check that the data actually is in the cache. */ for (i = 0; i < LINE_SIZE / sizeof (int); i++) { if (p1[i] != -1) abort (); } /* Check returning within the cache line. */ p2 = cache_fetch ((__ea void *) (aligned + sizeof (int))); if (p2 - p1 != 1) abort (); /* Finally, check that fetching an LS pointer returns that pointer. */ p1 = cache_fetch ((__ea char *) ls_block); if (p1 != ls_block) abort (); } /* Test 2: Eviction testing. */ void test2 (void) { addr aligned = ((((addr) block) + LINE_SIZE - 1) & -LINE_SIZE); int *p = NULL; int i = 0; /* First check that clean evictions don't write back. */ p = cache_fetch ((__ea void *) aligned); for (i = 0; i < LINE_SIZE / sizeof (int); i++) p[i] = 0; cache_evict ((__ea void *) aligned); memcpy_ea ((__ea char *) ls_block, (__ea void *) aligned, LINE_SIZE); for (i = 0; i < LINE_SIZE / sizeof (int); i++) { if (ls_block[i] == 0) abort (); } /* Now check that dirty evictions do write back. */ p = cache_fetch_dirty ((__ea void *) aligned, LINE_SIZE); for (i = 0; i < LINE_SIZE / sizeof (int); i++) p[i] = 0; cache_evict ((__ea void *) aligned); memcpy_ea ((__ea char *) ls_block, (__ea void *) aligned, LINE_SIZE); for (i = 0; i < LINE_SIZE / sizeof (int); i++) { if (ls_block[i] != 0) abort (); } /* Finally, check that non-atomic writeback only writes dirty bytes. */ for (i = 0; i < LINE_SIZE / sizeof (int); i++) { p = cache_fetch_dirty ((__ea void *) (aligned + i * sizeof (int)), (i % 2) * sizeof (int)); p[0] = -1; } cache_evict ((__ea void *) aligned); memcpy_ea ((__ea char *) ls_block, (__ea void *) aligned, LINE_SIZE); for (i = 0; i < LINE_SIZE / sizeof (int); i++) { if ((ls_block[i] == -1) && (i % 2 == 0)) abort (); if ((ls_block[i] == 0) && (i % 2 == 1)) abort (); } } /* Test LS forced-eviction. */ void test3 (void) { addr aligned = ((((addr) bigblock) + LINE_SIZE - 1) & -LINE_SIZE); char *test = NULL; char *ls = NULL; int i = 0; /* Init memory, fill the cache to capacity. */ ls = cache_fetch_dirty ((__ea void *) aligned, LINE_SIZE); for (i = 1; i < (CACHE_SIZE / LINE_SIZE); i++) cache_fetch_dirty ((__ea void *) (aligned + i * LINE_SIZE), LINE_SIZE); memset (ls, -1, LINE_SIZE); test = cache_fetch ((__ea void *) (aligned + CACHE_SIZE)); /* test == ls indicates cache collision. */ if (test != ls) abort (); /* Make sure it actually wrote the cache line. */ for (i = 0; i < LINE_SIZE; i++) { if (ls[i] != 0) abort (); } ls = cache_fetch ((__ea void *) aligned); /* test != ls indicates another entry was evicted. */ if (test == ls) abort (); /* Make sure that the previous eviction actually wrote back. */ for (i = 0; i < LINE_SIZE; i++) { if (ls[i] != 0xFF) abort (); } } int main (int argc, char **argv) { init_mem (); test1 (); test2 (); test3 (); return 0; }