summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src/lib')
-rw-r--r--gnuradio-core/src/lib/filter/Makefile.am8
-rw-r--r--gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c90
-rw-r--r--gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h47
-rw-r--r--gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c3
-rw-r--r--gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc91
-rw-r--r--gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h45
-rw-r--r--gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc25
7 files changed, 292 insertions, 17 deletions
diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am
index bf97d6cdc..ebc7ad203 100644
--- a/gnuradio-core/src/lib/filter/Makefile.am
+++ b/gnuradio-core/src/lib/filter/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2001,2002,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+# Copyright 2001,2002,2004,2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -159,7 +159,9 @@ armv7_a_CODE = \
gr_fir_sysconfig_armv7_a.cc \
gr_cpu_armv7_a.cc \
gr_fir_fff_armv7_a.cc \
- dotprod_fff_armv7_a.c
+ dotprod_fff_armv7_a.c \
+ gr_fir_ccf_armv7_a.cc \
+ dotprod_ccf_armv7_a.c
armv7_a_qa_CODE = \
qa_dotprod_armv7_a.cc
@@ -312,6 +314,7 @@ noinst_HEADERS = \
assembly.h \
dotprod_fff_altivec.h \
dotprod_fff_armv7_a.h \
+ dotprod_ccf_armv7_a.h \
gr_fir_scc_simd.h \
gr_fir_scc_x86.h \
gr_fir_fcc_simd.h \
@@ -322,6 +325,7 @@ noinst_HEADERS = \
gr_fir_ccc_x86.h \
gr_fir_fff_altivec.h \
gr_fir_fff_armv7_a.h \
+ gr_fir_ccf_armv7_a.h \
gr_fir_fff_simd.h \
gr_fir_fff_x86.h \
gr_fir_fsf_simd.h \
diff --git a/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c
new file mode 100644
index 000000000..90bd2ee10
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dotprod_ccf_armv7_a.h>
+
+/*!
+ * \param x any value
+ * \param pow2 must be a power of 2
+ * \returns \p x rounded down to a multiple of \p pow2.
+ */
+static inline size_t
+gr_p2_round_down(size_t x, size_t pow2)
+{
+ return x & -pow2;
+}
+
+
+#if 0
+
+void
+dotprod_ccf_armv7_a(const float *a, const float *b, float *res, size_t n)
+{
+ size_t i;
+ res[0] = 0;
+ res[1] = 0;
+
+ for (i = 0; i < n; i++){
+ res[0] += a[2*i] * b[i];
+ res[1] += a[2*i+1] * b[i];
+ }
+}
+
+#else
+
+/*
+ * preconditions:
+ *
+ * n > 0 and a multiple of 4
+ * a 4-byte aligned
+ * b 16-byte aligned
+ */
+void
+dotprod_ccf_armv7_a(const float *a, const float *b, float *res, size_t n)
+{
+
+ asm volatile(
+ "vmov.f32 q14, #0.0 \n\t"
+ "vmov.f32 q15, #0.0 \n\t"
+ "1: \n\t"
+ "subs %2, %2, #4 \n\t"
+ "vld2.f32 {q0-q1}, [%0]! \n\t"
+ "vld1.f32 {q2}, [%1]! \n\t"
+ "vmla.f32 q14, q0, q2 \n\t"
+ "vmla.f32 q15, q1, q2 \n\t"
+ "bgt 1b \n\t"
+ "vpadd.f32 d0, d28, d29 \n\t"
+ "vpadd.f32 d1, d30, d31 \n\t"
+ "vpadd.f32 d0, d0, d1 \n\t"
+ "vst1.f32 {d0}, [%3] \n\t"
+
+ : "+&r"(a), "+&r"(b), "+&r"(n)
+ : "r"(res)
+ : "memory", "d0", "d1", "d2", "d3", "d4", "d5",
+ "d28", "d29", "d30", "d31" );
+}
+
+
+#endif
diff --git a/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h
new file mode 100644
index 000000000..7ee728ac4
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_DOTPROD_CCF_ARMV7_A_H
+#define INCLUDED_DOTPROD_CCF_ARMV7_A_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * <pre>
+ *
+ * preconditions:
+ *
+ * n > 0 and a multiple of 4
+ * a 4-byte aligned
+ * b 16-byte aligned
+ *
+ * </pre>
+ */
+void dotprod_ccf_armv7_a(const float *a, const float *b, float *res, size_t n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_DOTPROD_CCF_ARMV7_A_H */
diff --git a/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c
index bd1b88e22..c3275c331 100644
--- a/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c
+++ b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c
@@ -77,7 +77,8 @@ dotprod_fff_armv7_a(const float *a, const float *b, size_t n)
"vpadd.f32 d0, d16, d17 \n\t"
"vadd.f32 %0, s0, s1 \n\t"
: "=w"(s), "+r"(a), "+r"(b), "+r"(n)
- :: "q0", "q1", "q2", "q3", "q8", "q9");
+ :: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d16", "d17", "d18", "d19");
return s;
diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc
new file mode 100644
index 000000000..ac42b57b7
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc
@@ -0,0 +1,91 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gr_fir_ccf_armv7_a.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdexcept>
+#include <assert.h>
+#include <gr_math.h>
+#include <dotprod_ccf_armv7_a.h>
+
+#define FLOATS_PER_VEC 4
+
+gr_fir_ccf_armv7_a::gr_fir_ccf_armv7_a()
+ : gr_fir_ccf_generic(),
+ d_naligned_taps(0), d_aligned_taps(0)
+{
+}
+
+gr_fir_ccf_armv7_a::gr_fir_ccf_armv7_a (const std::vector<float> &new_taps)
+ : gr_fir_ccf_generic(new_taps),
+ d_naligned_taps(0), d_aligned_taps(0)
+{
+ set_taps(new_taps);
+}
+
+gr_fir_ccf_armv7_a::~gr_fir_ccf_armv7_a()
+{
+ if (d_aligned_taps){
+ free(d_aligned_taps);
+ d_aligned_taps = 0;
+ }
+}
+
+void
+gr_fir_ccf_armv7_a::set_taps(const std::vector<float> &inew_taps)
+{
+ gr_fir_ccf_generic::set_taps(inew_taps); // call superclass
+ d_naligned_taps = gr_p2_round_up(ntaps(), FLOATS_PER_VEC);
+
+ if (d_aligned_taps){
+ free(d_aligned_taps);
+ d_aligned_taps = 0;
+ }
+ void *p;
+ int r = posix_memalign(&p, sizeof(float), d_naligned_taps * sizeof(d_aligned_taps[0]));
+ if (r != 0){
+ throw std::bad_alloc();
+ }
+ d_aligned_taps = (float *) p;
+ memcpy(d_aligned_taps, &d_taps[0], ntaps() * sizeof(d_aligned_taps[0]));
+ for (size_t i = ntaps(); i < d_naligned_taps; i++)
+ d_aligned_taps[i] = 0.0;
+}
+
+
+gr_complex
+gr_fir_ccf_armv7_a::filter (const gr_complex input[])
+{
+ if (d_naligned_taps == 0)
+ return 0.0;
+
+ gr_complex result;
+ float *presult = reinterpret_cast<float *>(&result);
+ const float *pinput = reinterpret_cast<const float *>(input);
+
+ dotprod_ccf_armv7_a(pinput, d_aligned_taps, presult, d_naligned_taps);
+ return result;
+}
diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h
new file mode 100644
index 000000000..719ff4010
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_GR_FIR_CCF_ARMV7_A_H
+#define INCLUDED_GR_FIR_CCF_ARMV7_A_H
+
+#include <gr_fir_ccf_generic.h>
+
+/*!
+ * \brief armv7_a using NEON coprocessor version of gr_fir_ccf
+ */
+class gr_fir_ccf_armv7_a : public gr_fir_ccf_generic
+{
+protected:
+
+ size_t d_naligned_taps; // number of taps (multiple of 4)
+ float *d_aligned_taps; // 16-byte aligned, and zero padded to multiple of 4
+
+public:
+ gr_fir_ccf_armv7_a();
+ gr_fir_ccf_armv7_a(const std::vector<float> &taps);
+ ~gr_fir_ccf_armv7_a();
+
+ virtual void set_taps (const std::vector<float> &taps);
+ virtual gr_complex filter (const gr_complex input[]);
+};
+
+#endif /* INCLUDED_GR_FIR_CCF_ARMV7_A*_H */
diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc
index 34c7d4c01..71e622d37 100644
--- a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc
+++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2002,2008,2009 Free Software Foundation, Inc.
+ * Copyright 2002,2008,2009,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -28,6 +28,7 @@
#include <gr_fir_ccf.h>
#include <gr_fir_ccf_generic.h>
+#include <gr_fir_ccf_armv7_a.h>
#include <gr_fir_fcc.h>
#include <gr_fir_fcc_generic.h>
#include <gr_fir_fff.h>
@@ -51,13 +52,13 @@ using std::cerr;
* ----------------------------------------------------------------
*/
-#if 0
static gr_fir_ccf *
-make_gr_fir_ccf_altivec(const std::vector<float> &taps)
+make_gr_fir_ccf_armv7_a (const std::vector<float> &taps)
{
- return new gr_fir_ccf_altivec(taps);
+ return new gr_fir_ccf_armv7_a(taps);
}
+#if 0
static gr_fir_fcc *
make_gr_fir_fcc_altivec(const std::vector<gr_complex> &taps)
{
@@ -107,15 +108,13 @@ gr_fir_sysconfig_armv7_a::create_gr_fir_ccf (const std::vector<float> &taps)
{
static bool first = true;
-#if 0
- if (gr_cpu::has_altivec ()){
+ if (gr_cpu::has_armv7_a ()){
if (first){
- cerr << ">>> gr_fir_ccf: using altivec\n";
+ cerr << ">>> gr_fir_ccf: using armv7_a\n";
first = false;
}
- return make_gr_fir_ccf_altivec (taps);
+ return make_gr_fir_ccf_armv7_a (taps);
}
-#endif
if (0 && first){
cerr << ">>> gr_fir_ccf: handing off to parent class\n";
@@ -245,15 +244,13 @@ gr_fir_sysconfig_armv7_a::get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *inf
// invoke parent..
gr_fir_sysconfig_generic::get_gr_fir_ccf_info (info);
-#if 0
// add our stuff...
gr_fir_ccf_info t;
- if (gr_cpu::has_altivec ()){
- t.name = "altivec";
- t.create = make_gr_fir_ccf_altivec;
+ if (gr_cpu::has_armv7_a ()){
+ t.name = "armv7_a";
+ t.create = make_gr_fir_ccf_armv7_a;
(*info).push_back (t);
}
-#endif
}
void