This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, spu]: implement MFC tag manager


The following patch implements the MFC tag manager, as described in
section 4.3 of the CBEA Language Extensions document (version 2.5).

I have made one change to spu_mfcio.h worth pointing out.  Previously,
spu_mfcio.h included <stdint.h>, which posed no problems when the header
was #included by programs compiled once newlib headers are installed.
When newlib headers are not present (ie. during a bare build of the
compiler), libgcc will fail to compile because the tag manager source
files use spu_mfcio.h.  The workaround I chose provides the one needed
typedef (uint64_t) in spu_mfcio.h.  As this is not meant to be a
portable header, this seemed satisfactory.

Also, note that the new source files have the GPL runtime exception, as
they are linked into libgcc.

Okay for mainline (I presume deferred to stage 1)?

Ben


2007-10-24  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
            Ben Elliston  <bje@au.ibm.com>

        * config/spu/mfc_tag_release.c: New file.
        * config/spu/mfc_multi_tag_release.c: Likewise.
        * config/spu/mfc_multi_tag_reserve.c: Likewise.
        * config/spu/mfc_tag_release.c: Likewise.
        * config/spu/mfc_tag_reserve.c: Likewise.
        * config/spu/mfc_tag_table.c: Likewise.
        * config/spu/t-spu-elf (LIB2FUNCS_STATIC_EXTRA): Compile them.
        * config/spu/spu_mfcio.h: Avoid <stdint.h>.
        (uint64_t): Typedef.
        (MFC_TAG_INVALID, MFC_TAG_VALID): New macros.
        (mfc_tag_reserve, mfc_tag_release, mfc_multi_tag_reserve,
        mfc_multi_tag_release): Likewise.
        (__mfc_tag_reserve, __mfc_tag_release, __mfc_multi_tag_reserve,
        __mfc_multi_tag_release): Declare.

Index: gcc-trunk/gcc/config/spu/mfc_multi_tag_release.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-trunk/gcc/config/spu/mfc_multi_tag_release.c	2007-10-24 14:03:35.000000000 +1000
@@ -0,0 +1,77 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include <spu_mfcio.h>
+extern vector unsigned int __mfc_tag_table;
+
+/* Release a sequential group of tags from exclusive use. The sequential
+   group of tags is the range starting from <first_tag> through
+   <first_tag>+<number_of_tags>-1. Upon sucessful release, MFC_DMA_TAG_VALID
+   is returned and the tags become available for future reservation.
+
+   If the specified tags were not previously reserved, no action is
+   taken and MFC_DMA_TAG_INVALID is returned.  */
+
+unsigned int
+__mfc_multi_tag_release (unsigned int first_tag, unsigned int number_of_tags)
+{
+  vector unsigned int table_copy, tmp, tmp1;
+  vector unsigned int one = (vector unsigned int)
+        { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  vector unsigned int is_invalid;
+  unsigned int last_tag;
+  vector unsigned int has_been_reserved;
+
+  last_tag = first_tag + number_of_tags;
+
+  table_copy = spu_sl (one, number_of_tags);
+  table_copy = spu_rl (table_copy, -last_tag);
+  table_copy = spu_xor (table_copy, -1);
+
+  /* Make sure the tags are in range and valid.  */
+  tmp = spu_cmpgt (spu_promote(last_tag, 0), 32);
+  tmp1 = spu_cmpgt (spu_promote(number_of_tags, 0), 32);
+  is_invalid =  spu_cmpgt (spu_promote(first_tag, 0), 31);
+
+  /* All bits are set to 1 if invalid, 0 if valid.  */
+  is_invalid = spu_or (tmp, is_invalid);
+  is_invalid = spu_or (tmp1, is_invalid);
+
+  /* check whether these tags have been reserved */
+  tmp = spu_rlmask (one, (int)-number_of_tags);
+  tmp1 = spu_sl (__mfc_tag_table, first_tag);
+  has_been_reserved = spu_cmpgt(tmp1, tmp);
+
+  is_invalid = spu_or (has_been_reserved, is_invalid);
+
+  table_copy = spu_sel (__mfc_tag_table, table_copy, table_copy);
+  __mfc_tag_table = spu_sel (table_copy, __mfc_tag_table, is_invalid);
+
+  return spu_extract (is_invalid, 0);
+}
+
Index: gcc-trunk/gcc/config/spu/mfc_multi_tag_reserve.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-trunk/gcc/config/spu/mfc_multi_tag_reserve.c	2007-10-24 14:03:50.000000000 +1000
@@ -0,0 +1,89 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include <spu_mfcio.h>
+extern vector unsigned int __mfc_tag_table;
+
+/* Reserve a sequential group of tags for exclusive use.  The number of
+   tags to be reserved is specified by the <number_of_tags> parameter.
+   This routine returns the first tag ID for a sequential list of
+   available tags and marks them as reserved. The reserved group
+   of tags is in the range starting from the returned tag through
+   the returned tag + <number_of_tags>-1.
+
+   If the number of tags requested exceeds the number of available
+   sequential tags, then MFC_DMA_TAG_INVALID is returned indicating
+   that the request could not be serviced.  */
+
+unsigned int
+__mfc_multi_tag_reserve (unsigned int number_of_tags)
+{
+  vector unsigned int table_copy;
+  vector unsigned int one = (vector unsigned int)
+        { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  vector unsigned int count_busy, is_valid;
+  vector unsigned int count_total;
+  vector unsigned int count_avail = (vector unsigned int) { 0, 0, 0, 0 };
+  vector unsigned int index = (vector unsigned int) { 0, 0, 0, 0 };
+
+  table_copy = __mfc_tag_table;
+
+
+  /* count_busy: number of consecutive busy tags
+     count_avail: number of consecutive free tags
+     table_copy: temporary copy of the tag table
+     count_total: sum of count_busy and count_avail
+     index: index of the current working tag  */
+  do
+    {
+      table_copy = spu_sl (table_copy, count_avail);
+
+      count_busy = spu_cntlz (table_copy);
+      table_copy = spu_sl (table_copy, count_busy);
+      count_avail = spu_cntlz (spu_xor(table_copy, -1));
+      count_total = spu_add (count_busy, count_avail);
+      index = spu_add (index, count_total);
+    }
+  while (spu_extract (count_avail, 0) < number_of_tags
+	 && spu_extract (table_copy, 0) != 0);
+
+  index = spu_sub (index, count_avail);
+
+  /* is_valid is set to 0xFFFFFFFF if table_copy == 0, 0 otherwise.  */
+  is_valid = spu_cmpeq (table_copy, 0);
+  index = spu_sel (index, is_valid, is_valid);
+
+  /* Now I need to actually mark the tags as used.  */
+  table_copy = spu_sl (one, number_of_tags);
+  table_copy = spu_rl (table_copy, -number_of_tags - spu_extract (index, 0));
+  table_copy = spu_sel (table_copy, __mfc_tag_table, table_copy);
+  __mfc_tag_table = spu_sel (table_copy, __mfc_tag_table, is_valid);
+
+  return spu_extract (index, 0);
+}
+
Index: gcc-trunk/gcc/config/spu/mfc_tag_release.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-trunk/gcc/config/spu/mfc_tag_release.c	2007-10-24 14:04:46.000000000 +1000
@@ -0,0 +1,64 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include <spu_mfcio.h>
+extern vector unsigned int __mfc_tag_table;
+
+/* Release the specified DMA tag from exclusive use.  Once released, the
+   tag is available for future reservation.  Upon sucessful release,
+   MFC_DMA_TAG_VALID is returned.  If the specified tag is not in the
+   range 0 to 31, or had not been reserved, no action is taken and
+   MFC_DMA_TAG_INVALID is returned.  */
+
+unsigned int
+__mfc_tag_release (unsigned int tag)
+{
+  vector unsigned int is_invalid;
+  vector unsigned int mask = (vector unsigned int)
+	{ 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
+  vector signed int zero = (vector signed int) { 0, 0, 0, 0 };
+
+  vector signed int has_been_reserved;
+
+  /* Check if the tag is out of range.  */
+  is_invalid = spu_cmpgt (spu_promote (tag, 0), 31);
+
+  /* Check whether the tag has been reserved, set to all 1 if has not
+     been reserved, 0 otherwise.  */
+  has_been_reserved = (vector signed int) spu_rl (__mfc_tag_table, tag);
+  has_been_reserved = (vector signed int) spu_cmpgt (zero, has_been_reserved);
+
+  /* Set invalid.  */
+  is_invalid = spu_or ((vector unsigned int) has_been_reserved, is_invalid);
+
+  mask = spu_rlmask (mask, (int)(-tag));
+  __mfc_tag_table = spu_or (__mfc_tag_table, mask);
+
+  return spu_extract(is_invalid, 0);
+}
+
Index: gcc-trunk/gcc/config/spu/mfc_tag_reserve.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-trunk/gcc/config/spu/mfc_tag_reserve.c	2007-10-24 15:37:30.000000000 +1000
@@ -0,0 +1,56 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include <spu_mfcio.h>
+extern vector unsigned int __mfc_tag_table;
+
+/* Reserves a DMA tag for exclusive use.  This routine returns an available
+   tag id in the range 0 to 31 and marks the tag as reserved.  If no tags
+   are available, MFC_DMA_TAG_INVALID is returned indicating that all tags
+   are already reserved.  */
+
+unsigned int
+__mfc_tag_reserve (void)
+{
+  vector unsigned int mask = (vector unsigned int)
+	{ 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
+  vector unsigned int count_zeros, is_valid;
+  vector signed int count_neg;
+
+  count_zeros = spu_cntlz (__mfc_tag_table);
+  count_neg = spu_sub (0, (vector signed int) count_zeros);
+
+  mask = spu_rlmask (mask, (vector signed int) count_neg);
+  __mfc_tag_table = spu_andc (__mfc_tag_table, mask);
+
+  is_valid = spu_cmpeq (count_zeros, 32);
+  count_zeros = spu_sel (count_zeros, is_valid, is_valid);
+
+  return spu_extract (count_zeros, 0);
+}
+
Index: gcc-trunk/gcc/config/spu/mfc_tag_table.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-trunk/gcc/config/spu/mfc_tag_table.c	2007-10-24 14:04:51.000000000 +1000
@@ -0,0 +1,45 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC 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 GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+
+/* The free tag table used by the MFC tag manager, with tag0
+   reserved for the overlay manager.  */
+__vector unsigned int
+__mfc_tag_table = (__vector unsigned int) { 0x7FFFFFFF, -1, -1, -1 };
+
+/* Arrange to release tag0 if overlays are not present.  */
+static void __mfc_tag_init (void) __attribute__ ((constructor));
+
+static void
+__mfc_tag_init (void)
+{
+  extern void _ovly_table __attribute__ ((weak));
+
+  if (&_ovly_table == 0)
+    __mfc_tag_table = (__vector unsigned int) { -1, -1, -1, -1 };
+}
Index: gcc-trunk/gcc/config/spu/spu_mfcio.h
===================================================================
--- gcc-trunk.orig/gcc/config/spu/spu_mfcio.h	2007-10-24 11:55:18.000000000 +1000
+++ gcc-trunk/gcc/config/spu/spu_mfcio.h	2007-10-24 15:34:56.000000000 +1000
@@ -25,8 +25,8 @@
 #define __SPU_MFCIO_H__ 1
 
 #include <spu_intrinsics.h>
-#include <stdint.h>
 
+typedef unsigned long long uint64_t;
 
 /****************************************************************/
 /* DMA list element structure*/
@@ -267,4 +267,25 @@
 #define spu_write_srr0(srr0)          spu_writech(SPU_WrSRR0,srr0)
 #define spu_read_srr0()               spu_readch(SPU_RdSRR0)
 
+
+/* MFC Tag Manager */
+
+#define MFC_TAG_INVALID 0xFFFFFFFF
+#define MFC_TAG_VALID   0x00000000
+
+#define mfc_tag_reserve() \
+	__mfc_tag_reserve()
+#define mfc_tag_release(tag) \
+	__mfc_tag_release((tag))
+#define mfc_multi_tag_reserve(nr_tags) \
+	__mfc_multi_tag_reserve((nr_tags))
+#define mfc_multi_tag_release(tag, nr_tags) \
+	__mfc_multi_tag_release((tag),(nr_tags))
+
+extern unsigned int __mfc_tag_reserve (void);
+extern unsigned int __mfc_tag_release (unsigned int);
+extern unsigned int __mfc_multi_tag_reserve (unsigned int);
+extern unsigned int __mfc_multi_tag_release (unsigned int, unsigned int);
+
+
 #endif /* __SPU_MFCIO_H__ */
Index: gcc-trunk/gcc/config/spu/t-spu-elf
===================================================================
--- gcc-trunk.orig/gcc/config/spu/t-spu-elf	2007-10-24 13:34:36.000000000 +1000
+++ gcc-trunk/gcc/config/spu/t-spu-elf	2007-10-24 13:34:36.000000000 +1000
@@ -31,7 +31,12 @@
 TARGET_LIBGCC2_CFLAGS = -fPIC -D__word__=SI -mwarn-reloc
 
 LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/spu/float_unssidf.c \
-			 $(srcdir)/config/spu/float_unsdidf.c
+			 $(srcdir)/config/spu/float_unsdidf.c \
+			 $(srcdir)/config/spu/mfc_tag_table.c \
+			 $(srcdir)/config/spu/mfc_tag_reserve.c \
+			 $(srcdir)/config/spu/mfc_tag_release.c \
+			 $(srcdir)/config/spu/mfc_multi_tag_reserve.c \
+			 $(srcdir)/config/spu/mfc_multi_tag_release.c
 
 LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
    $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
Index: gcc-trunk/gcc/testsuite/gcc.target/spu/tag_manager.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-trunk/gcc/testsuite/gcc.target/spu/tag_manager.c	2007-10-24 14:07:58.000000000 +1000
@@ -0,0 +1,312 @@
+/* Copyright (C) 2007 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 2 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 COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* { dg-do run } */
+
+#include <spu_mfcio.h>
+
+/* This test directly accesses the internal table used
+   by the MFC tag manager.  */
+extern vector unsigned int __mfc_tag_table;
+
+
+/* This tag tests invalid tag release.  Invalid tag release does
+   nothing to the tag table.  */
+void
+test_tag_release01 (void)
+{
+  unsigned int copy;
+  copy = spu_extract (__mfc_tag_table, 0);
+
+  mfc_tag_release (35);
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+}
+
+/* More invalid release tests.  */
+void
+test_tag_release_invalid (void)
+{
+  unsigned int copy;
+  copy = spu_extract (__mfc_tag_table, 0);
+
+  if (mfc_tag_release (32) != MFC_TAG_INVALID)
+    abort ();
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+
+  if (mfc_tag_release (17) != MFC_TAG_INVALID)
+    abort ();
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+}
+
+/* Invalid multiple-tag release tests.  */
+void
+test_tag_group_release_invalid (void)
+{
+  unsigned int copy;
+  copy = spu_extract (__mfc_tag_table, 0);
+
+  if (mfc_multi_tag_release (32, 10) != MFC_TAG_INVALID)
+    abort ();
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+
+  if (mfc_multi_tag_release (28, 10) != MFC_TAG_INVALID)
+    abort ();
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+
+  if (mfc_multi_tag_release (17, 10) != MFC_TAG_INVALID)
+    abort ();
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+
+  if (mfc_multi_tag_release (32, 10) != MFC_TAG_INVALID)
+    abort ();
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+}
+
+/* The tag table should be in a pristine mode to run this test.  */
+void
+test_tag_reserve01 (void)
+{
+  unsigned int correct_table[32] =
+    {
+		  0x80000000, 0xC0000000, 0xE0000000,
+      0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000,
+      0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
+      0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000,
+      0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000,
+      0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00,
+      0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0,
+      0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
+      0xFFFFFFFF
+    };
+
+  unsigned int tag;
+  unsigned int i;
+
+  for (i = 0; i < 32; i++)
+    {
+      tag = mfc_tag_reserve ();
+      if (tag != i)
+	abort ();
+    }
+
+  for (i = 0; i < 32; i++)
+    {
+      tag = mfc_tag_reserve ();
+      if (tag != MFC_TAG_INVALID)
+	abort ();
+    }
+
+  for (i = 0; i < 32; i++)
+    {
+      mfc_tag_release (i);
+      if (spu_extract (__mfc_tag_table, 0) != correct_table[i])
+	abort ();
+    }
+}
+
+/* The tag table should be in a pristine mode to run this test.  */
+void
+test_tag_reserve02 (void)
+{
+  unsigned int correct_table[32] =
+    {
+      0x80000000, 0xC0000000, 0xA0000000, 0xF0000000,
+      0xA8000000, 0xFC000000, 0xAA000000, 0xFF000000,
+      0xAA800000, 0xFFC00000, 0xAAA00000, 0xFFF00000,
+      0xAAA80000, 0xFFFC0000, 0xAAAA0000, 0xFFFF0000,
+      0xAAAA8000, 0xFFFFC000, 0xAAAAA000, 0xFFFFF000,
+      0xAAAAA800, 0xFFFFFC00, 0xAAAAAA00, 0xFFFFFF00,
+      0xAAAAAA80, 0xFFFFFFC0, 0xAAAAAAA0, 0xFFFFFFF0,
+      0xAAAAAAA8, 0xFFFFFFFC, 0xAAAAAAAA, 0xFFFFFFFF
+    };
+
+  unsigned int correct_table2[32] =
+    {
+      0x80000000, 0xEAAAAAAA, 0xA0000000, 0xFAAAAAAA,
+      0xA8000000, 0xFEAAAAAA, 0xAA000000, 0xFFAAAAAA,
+      0xAA800000, 0xFFEAAAAA, 0xAAA00000, 0xFFFAAAAA,
+      0xAAA80000, 0xFFFEAAAA, 0xAAAA0000, 0xFFFFAAAA,
+      0xAAAA8000, 0xFFFFEAAA, 0xAAAAA000, 0xFFFFFAAA,
+      0xAAAAA800, 0xFFFFFEAA, 0xAAAAAA00, 0xFFFFFFAA,
+      0xAAAAAA80, 0xFFFFFFEA, 0xAAAAAAA0, 0xFFFFFFFA,
+      0xAAAAAAA8, 0xFFFFFFFE, 0xAAAAAAAA, 0xFFFFFFFF
+    };
+
+  unsigned int tag;
+  unsigned int i;
+
+  /* Reserve all 32 tags.  */
+  for (i = 0; i < 32; i++)
+    {
+      tag = mfc_tag_reserve();
+      if (tag != i)
+	abort ();
+    }
+
+  for (i = 0; i < 32; i++)
+    {
+      tag = mfc_tag_reserve();
+      if (tag != MFC_TAG_INVALID)
+	abort ();
+    }
+
+  /* Release only 16 tags with a stride of 2.  */
+  for (i = 0; i < 32; i += 2)
+    {
+      mfc_tag_release (i);
+      if (spu_extract (__mfc_tag_table, 0) != correct_table[i])
+	abort ();
+    }
+
+  /* Release the other 16 tags with a stride of 2.  */
+  for (i = 1; i < 32; i += 2)
+    {
+      mfc_tag_release (i);
+      if (spu_extract (__mfc_tag_table, 0) != correct_table2[i])
+	abort ();
+    }
+}
+
+/* The tag table should be in a pristine mode to run this test.  */
+void
+test_tag_reserve03 (void)
+{
+  unsigned int tag;
+  unsigned int i;
+
+  /* Reserve all 32 tags.  */
+  for (i = 0; i < 32; i++)
+    {
+      tag = mfc_tag_reserve ();
+      if (tag != i)
+	abort ();
+    }
+
+  for (i = 0; i < 32; i++)
+    {
+      tag = mfc_tag_reserve ();
+      if (tag != MFC_TAG_INVALID)
+	abort ();
+    }
+
+  /* Release only 16 tags with a stride of 2.  */
+  for (i = 0; i < 32; i += 2)
+    mfc_tag_release (i);
+
+  /* Now let's re-reserve those tags.  */
+  for (i = 0; i < 32; i += 2)
+    {
+      tag = mfc_tag_reserve ();
+      if (tag != i)
+	abort ();
+    }
+
+  /* Release all tags.  */
+  for (i = 0; i < 32; i++)
+    mfc_tag_release (i);
+
+  if (spu_extract (__mfc_tag_table,0) != 0xFFFFFFFF)
+    abort ();
+}
+
+
+void
+test_tag_group_reserve (void)
+{
+  unsigned int tag;
+  unsigned int i;
+  unsigned int copy;
+
+  /* Reserve all tags.  */
+  for (i = 0; i < 32; i++)
+    mfc_tag_reserve();
+
+  /* Release the first 4. */
+  for (i = 0; i < 4; i++)
+    mfc_tag_release (i);
+
+  /* Release tag 5 to 7.  */
+  for (i = 5; i < 8; i++)
+    mfc_tag_release (i);
+
+  /* Release tag 9 to 19.  */
+  for (i = 9; i < 20; i++)
+    mfc_tag_release (i);
+
+  /* Tag table should be 0xF77FF000.  */
+  if (spu_extract (__mfc_tag_table, 0) != 0xF77FF000)
+    abort ();
+
+
+  /* Verify invalid release is detected.  */
+  copy = spu_extract (__mfc_tag_table, 0);
+  if (mfc_multi_tag_release (1, 5) != MFC_TAG_INVALID)
+    abort ();
+  if (copy != spu_extract (__mfc_tag_table, 0))
+    abort ();
+
+
+  /* Reserve multiple tags.  */
+  tag = mfc_multi_tag_reserve (5);
+  if (tag != 9)
+    abort ();
+
+  /* Tag table should be 0xF703F000.  */
+  if (spu_extract (__mfc_tag_table, 0) != 0xF703F000)
+    abort ();
+
+
+  /* Release 5 tags in the group.  */
+  mfc_multi_tag_release (tag, 5);
+
+  /* Tag table should be 0xF77FF000.  */
+  if (spu_extract (__mfc_tag_table, 0) != 0xF77FF000)
+    abort ();
+
+
+  /* This call should not do anything.  */
+  mfc_multi_tag_release (32, 5);
+
+  /* Tag table should be 0xF77FF000.  */
+  if (spu_extract (__mfc_tag_table, 0) != 0xF77FF000)
+    abort ();
+}
+
+
+int
+main (void)
+{
+  test_tag_release01 ();
+  test_tag_release_invalid ();
+  test_tag_group_release_invalid ();
+
+  test_tag_reserve01 ();
+  test_tag_reserve02 ();
+  test_tag_reserve03 ();
+
+  test_tag_group_reserve ();
+
+  return 0;
+}
+



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]