public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, spu]: implement MFC tag manager
@ 2007-10-25 12:11 Ben Elliston
  2007-11-07  1:34 ` trevor_smigiel
  0 siblings, 1 reply; 8+ messages in thread
From: Ben Elliston @ 2007-10-25 12:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: pinskia, Trevor_Smigiel, Ulrich.Weigand

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;
+}
+


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH, spu]: implement MFC tag manager
  2007-10-25 12:11 [PATCH, spu]: implement MFC tag manager Ben Elliston
@ 2007-11-07  1:34 ` trevor_smigiel
  2007-11-07  2:09   ` Ben Elliston
  0 siblings, 1 reply; 8+ messages in thread
From: trevor_smigiel @ 2007-11-07  1:34 UTC (permalink / raw)
  To: Ben Elliston; +Cc: gcc-patches, pinskia, Ulrich.Weigand

Ben,

Regarding the <stdint.h> change, are you at all concerned about
backwards compatibility fou spu_mfcio.h?  Someone may be relying on
stdint.h to be included, whether by accident or on purpose.  Of course,
it is easy for the user to fix problem.  Is it appropriate to use the
name uint64_t?

The specification uses both of the names uint64_t and uint32_t, though
the implementation only uses uint64_t.  If a programmer uses our spec
as a reference they might expect uint32_t to be defined as well.

I guess I would argue for leaving stdint.h in for compatibility and to
keep uint32_t defined.   And use an #ifdef while building libgcc.

Trevor


* Ben Elliston <bje@au1.ibm.com> [2007-10-24 22:20]:
> 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;
> +}
> +
> 
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH, spu]: implement MFC tag manager
  2007-11-07  1:34 ` trevor_smigiel
@ 2007-11-07  2:09   ` Ben Elliston
  2007-11-07  2:38     ` trevor_smigiel
  2007-11-14 23:34     ` trevor_smigiel
  0 siblings, 2 replies; 8+ messages in thread
From: Ben Elliston @ 2007-11-07  2:09 UTC (permalink / raw)
  To: trevor_smigiel; +Cc: gcc-patches, pinskia, Ulrich.Weigand

Hi Trevor

> Regarding the <stdint.h> change, are you at all concerned about
> backwards compatibility fou spu_mfcio.h?  Someone may be relying on
> stdint.h to be included, whether by accident or on purpose.  Of course,
> it is easy for the user to fix problem.  Is it appropriate to use the
> name uint64_t?

Oh, good point.

> I guess I would argue for leaving stdint.h in for compatibility and to
> keep uint32_t defined.   And use an #ifdef while building libgcc.

How about if I use an IN_LIBGCC test to ensure that the code can be
compiled without spu_mfcio.h for libgcc, but does not change behaviour
for users #including an installed spu_mfcio.h?  OK with that change?

Cheers, Ben

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH, spu]: implement MFC tag manager
  2007-11-07  2:09   ` Ben Elliston
@ 2007-11-07  2:38     ` trevor_smigiel
  2007-11-14 23:34     ` trevor_smigiel
  1 sibling, 0 replies; 8+ messages in thread
From: trevor_smigiel @ 2007-11-07  2:38 UTC (permalink / raw)
  To: Ben Elliston; +Cc: gcc-patches, pinskia, Ulrich.Weigand

> > I guess I would argue for leaving stdint.h in for compatibility and to
> > keep uint32_t defined.   And use an #ifdef while building libgcc.
> 
> How about if I use an IN_LIBGCC test to ensure that the code can be
> compiled without spu_mfcio.h for libgcc, but does not change behaviour
> for users #including an installed spu_mfcio.h?  OK with that change?
> 
> Cheers, Ben

Yeah, I think that's ok.

I'm still testing the patch.  I'll let you know ASAP if it is ok.

Trevor

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH, spu]: implement MFC tag manager
  2007-11-07  2:09   ` Ben Elliston
  2007-11-07  2:38     ` trevor_smigiel
@ 2007-11-14 23:34     ` trevor_smigiel
  2007-11-20 11:33       ` Ben Elliston
  1 sibling, 1 reply; 8+ messages in thread
From: trevor_smigiel @ 2007-11-14 23:34 UTC (permalink / raw)
  To: Ben Elliston; +Cc: gcc-patches, pinskia, Ulrich.Weigand

Ben,

Given this change the patch is OK.

Trevor

* Ben Elliston <bje@au1.ibm.com> [2007-11-06 18:15]:
> Hi Trevor
> 
> > Regarding the <stdint.h> change, are you at all concerned about
> > backwards compatibility fou spu_mfcio.h?  Someone may be relying on
> > stdint.h to be included, whether by accident or on purpose.  Of course,
> > it is easy for the user to fix problem.  Is it appropriate to use the
> > name uint64_t?
> 
> Oh, good point.
> 
> > I guess I would argue for leaving stdint.h in for compatibility and to
> > keep uint32_t defined.   And use an #ifdef while building libgcc.
> 
> How about if I use an IN_LIBGCC test to ensure that the code can be
> compiled without spu_mfcio.h for libgcc, but does not change behaviour
> for users #including an installed spu_mfcio.h?  OK with that change?
> 
> Cheers, Ben
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH, spu]: implement MFC tag manager
  2007-11-14 23:34     ` trevor_smigiel
@ 2007-11-20 11:33       ` Ben Elliston
  0 siblings, 0 replies; 8+ messages in thread
From: Ben Elliston @ 2007-11-20 11:33 UTC (permalink / raw)
  To: trevor_smigiel; +Cc: gcc-patches, pinskia, Ulrich.Weigand

Hi Trevor

> Given this change the patch is OK.

Having given this a bit more thought, I think this will be the wrong
approach.  While it's quite common to use the IN_LIBGCC guard to
conditionally control compilation of code for libgcc and the compiler
proper, I can't think of any instances where this is done in an
installed header.  Using "IN_LIBGCC" would pollute the user's namespace,
given that it is not prefixed with __.

I'll see if I can find a cleaner way to work around this and will post a
revised patch.

Cheers, Ben


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH, spu]: implement MFC tag manager
  2007-10-29 21:22 Ben Elliston
@ 2007-11-07  1:02 ` Ben Elliston
  0 siblings, 0 replies; 8+ messages in thread
From: Ben Elliston @ 2007-11-07  1:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor_Smigiel

Ping**2?
   http://gcc.gnu.org/ml/gcc-patches/2007-10/msg01439.html

Thanks, Ben


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH, spu]: implement MFC tag manager
@ 2007-10-29 21:22 Ben Elliston
  2007-11-07  1:02 ` Ben Elliston
  0 siblings, 1 reply; 8+ messages in thread
From: Ben Elliston @ 2007-10-29 21:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor_Smigiel

Ping?
  http://gcc.gnu.org/ml/gcc-patches/2007-10/msg01439.html

Thanks, Ben


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-11-20  2:44 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-25 12:11 [PATCH, spu]: implement MFC tag manager Ben Elliston
2007-11-07  1:34 ` trevor_smigiel
2007-11-07  2:09   ` Ben Elliston
2007-11-07  2:38     ` trevor_smigiel
2007-11-14 23:34     ` trevor_smigiel
2007-11-20 11:33       ` Ben Elliston
2007-10-29 21:22 Ben Elliston
2007-11-07  1:02 ` Ben Elliston

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).