diff options
Diffstat (limited to 'gnuradio-core/src/lib')
-rw-r--r-- | gnuradio-core/src/lib/filter/Makefile.am | 8 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c | 90 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h | 47 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c | 3 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc | 91 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h | 45 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc | 25 |
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 |