diff options
104 files changed, 4325 insertions, 2343 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f43b8f7a..dad398e8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) # Set the version information here set(VERSION_INFO_MAJOR_VERSION 3) set(VERSION_INFO_API_COMPAT 6) -set(VERSION_INFO_MINOR_VERSION 0) +set(VERSION_INFO_MINOR_VERSION 1) set(VERSION_INFO_MAINT_VERSION git) include(GrVersion) #setup version info @@ -228,6 +228,7 @@ add_subdirectory(gruel) add_subdirectory(gnuradio-core) add_subdirectory(grc) +add_subdirectory(gr-fft) add_subdirectory(gr-atsc) add_subdirectory(gr-audio) add_subdirectory(gr-comedi) @@ -46,21 +46,16 @@ http://gnuradio.org/redmine/projects/gnuradio/wiki/DevelopingWithGit How to Build GNU Radio: - (1) Ensure that you've satisfied the external dependencies listed - below. The word "system" is used to mean "operating system - and/or distribution", and means a full operating system, - including kernel, user-space utilties, and a packaging system - for additional software. On Linux, this means what - "distribution" means. - - The following GNU/Linux distributions are known to come with all - required dependencies pre-packaged: Ubuntu >8.10, SuSE 10.0 (the - pay version, not the free download), Fedora Core >9. Other - distribution may work too. We know these three are easy. The - required packages may be contained on your installation CD/DVD, - or may be loaded over the net. The specifics vary depending on - your GNU/Linux distribution. +For more complete instructions, see the "Building GNU Radio" page in +the GNU Radio manual (can be built or found online at +http://gnuradio.org/doc/doxygen/page_build.html). +See these steps fow a quick build guide. + + (1) Ensure that you've satisfied the external dependencies. These + dependencies are listed in the manual's build page and are not + presented here to reduce duplication errors. + On systems using pkgsrc (e.g. NetBSD and Dragonfly), build meta-packages/gnuradio, which will build a previous release and force installation of the dependencies. Then pkg_delete the @@ -105,147 +100,20 @@ with '-O3', which is the default. ------------------------------------------------------------------------------- - External dependencies + NOTES ------------------------------------------------------------------------------- -Prerequisites: Before trying to build these from source, please try -your system's installation tool (apt-get, pkg_install, YaST, yum, -urpmi, etc.) first. Most recent systems have these packages -available. - -You'll need to do a bit of sleuthing to figure out what your OS and -packaging system calls these. If your system uses the convention of -splitting files needed to run programs compiled with foo and files -needed to do the compilation into packages named foo and foo-devel, -install both packages. (Most GNU/Linux systems are like this, but -pkgsrc is not and instead uses -devel to indicate a package of a -not-yet-released or unstable version.) - -For those using pkgsrc, see gnuradio-pkg_chk.conf. Those not using -pkgsrc may also find the list useful. - -(0) GNU make - -It used to be required to have a "reasonable make", meaning GNU make, -BSD make, or perhaps Solaris make. It is now required to use GNU -make. Version 3.81 should certainly work; the intent is not to -require the bleeding edge. - -Note that the examples below are written with "make". They probably -should say "gmake", as GNU make is installed as gmake when it is not -the native make. - -(1) cmake 2.6 or later http://www.cmake.org/cmake/resources/software.html - -(2) pkgconfig 0.15.0 or later http://www.freedesktop.org/Software/pkgconfig - -From the web site: - -pkgconfig is a system for managing library compile/link flags that -works with automake and autoconf. It replaces the ubiquitous *-config -scripts you may have seen with a single tool. - - -(3) FFTW 3.0 or later http://www.fftw.org - -IMPORTANT!!! When building FFTW, you MUST use the --enable-single and ---enable-shared configure options. This builds the single precision -floating point version which we use. You should also use either the ---enable-3dnow or --enable-sse options if you're on an Athlon or Pentium -respectively. - -GNU/Linux packages of single-precision fftw are typically called -fftw3f. - -In systems using pkgsrc, install math/fftwf, which provides the -single-precision libraries. - - -(4) Python 2.5 or later http://www.python.org - -Python 2.5 or later is now required. If your system splits -python into a bunch of separate packages including python-devel or -libpython you'll most likely need those too. - - -(5) Numpy python library http://numeric.scipy.org - -Provides a high performance array type for Python. -http://numpy.scipy.org -http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=175103 - - -(6) The Boost C++ Libraries (1.35 or later) http://www.boost.org - -We use Smart Pointers, the thread library and a bunch of other boost stuff. -If your system doesn't have boost 1.35 or later, see README.building-boost -for additional info. (Note: Mac OSX systems require 1.37 or later.) - - -(7) cppunit 1.9.14 or later. http://cppunit.sourceforge.net - -Unit testing framework for C++. - - -(8) Simple Wrapper Interface Generator. http://www.swig.org - -As of repository version 4045, gnuradio requires version 1.3.31 or newer. - - -(9) GNU Scientific Library (gsl) 1.10 or later - -The GNU Radio core library uses some routines from here. - - -Optional, but nice to have: - -(10) wxPython. Python binding for the wxWidgets GUI framework. Use -version 2.8 or later. Again, almost all systems have this -available. - -As a last resort, build it from source (not recommended!) -http://www.wxpython.org - -(11) xmlto version ? or later. http://cyberelk.net/tim/xmlto/index.html - -Wrapper for XML conversion tools to ease e.g. making html from docbook. - -(12) Python Cheetah extensions 2.0.0 or later -(13) Python lxml wrappers 2.0.0 or later -(14) Python gtk wrappers 2.10.0 or later - -The GNU Radio Companion application requires these additional Python libraries -to be installed. - -The gr-qtgui requires these packages: - -(15) Qt 4.4 or later -(16) Qwt 5.2 or later -(17) PyQt 4.4 or later -(18) PyQwt 5.2 or later - -It is also useful to have Python's Scipy and Matplot lib packages to -run some of the example. - ----------------------------------------------------------------- - -If you have doxygen installed, the build process creates -documentation for the class hierarchy etc. Point your browser at -gnuradio/gnuradio-core/doc/html/index.html - - To run the examples you may need to set PYTHONPATH. Note that the prefix and python version number in the path needs to match your installed version of python. - $ export PYTHONPATH=/usr/local/lib/python2.5/site-packages + $ export PYTHONPATH=/usr/local/lib/python2.7/dist-packages You may want to add this to your shell init file (~/.bash_profile if you use bash). - Another handy trick if for example your fftw includes and libs are installed in, say ~/local/include and ~/local/lib, instead of /usr/local is this: diff --git a/cmake/Modules/FindJack.cmake b/cmake/Modules/FindJack.cmake index c6810c011..4bdfe0a7e 100644 --- a/cmake/Modules/FindJack.cmake +++ b/cmake/Modules/FindJack.cmake @@ -51,24 +51,19 @@ else (JACK_LIBRARIES AND JACK_INCLUDE_DIRS) /sw/lib ) - if (JACK_LIBRARY) + if (JACK_LIBRARY AND JACK_INCLUDE_DIR) set(JACK_FOUND TRUE) - endif (JACK_LIBRARY) - set(JACK_INCLUDE_DIRS - ${JACK_INCLUDE_DIR} - ) + set(JACK_INCLUDE_DIRS + ${JACK_INCLUDE_DIR} + ) - if (JACK_FOUND) set(JACK_LIBRARIES ${JACK_LIBRARIES} ${JACK_LIBRARY} ) - endif (JACK_FOUND) - if (JACK_INCLUDE_DIRS AND JACK_LIBRARIES) - set(JACK_FOUND TRUE) - endif (JACK_INCLUDE_DIRS AND JACK_LIBRARIES) + endif (JACK_LIBRARY AND JACK_INCLUDE_DIR) if (JACK_FOUND) if (NOT JACK_FIND_QUIETLY) diff --git a/cmake/Modules/FindPortaudio.cmake b/cmake/Modules/FindPortaudio.cmake index 4b7175438..61e4ae23a 100644 --- a/cmake/Modules/FindPortaudio.cmake +++ b/cmake/Modules/FindPortaudio.cmake @@ -4,104 +4,32 @@ # PORTAUDIO_FOUND - system has Portaudio # PORTAUDIO_INCLUDE_DIRS - the Portaudio include directory # PORTAUDIO_LIBRARIES - Link these to use Portaudio -# PORTAUDIO_DEFINITIONS - Compiler switches required for using Portaudio -# PORTAUDIO_VERSION - Portaudio version -# -# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org> -# -# Redistribution and use is allowed according to the terms of the New BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. -# - - -if (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS) - # in cache already - set(PORTAUDIO_FOUND TRUE) -else (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS) - if (NOT WIN32) - include(FindPkgConfig) - pkg_check_modules(PORTAUDIO2 portaudio-2.0) - endif (NOT WIN32) - - if (PORTAUDIO2_FOUND) - set(PORTAUDIO_INCLUDE_DIRS - ${PORTAUDIO2_INCLUDE_DIRS} - ) - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(PORTAUDIO_LIBRARIES "${PORTAUDIO2_LIBRARY_DIRS}/lib${PORTAUDIO2_LIBRARIES}.dylib") - else (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(PORTAUDIO_LIBRARIES - ${PORTAUDIO2_LIBRARIES} - ) - endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(PORTAUDIO_VERSION - 19 - ) - set(PORTAUDIO_FOUND TRUE) - else (PORTAUDIO2_FOUND) - find_path(PORTAUDIO_INCLUDE_DIR - NAMES - portaudio.h - PATHS - /usr/include - /usr/local/include - /opt/local/include - /sw/include - ) - - find_library(PORTAUDIO_LIBRARY - NAMES - portaudio - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib - ) - - find_path(PORTAUDIO_LIBRARY_DIR - NAMES - portaudio - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib - ) - - set(PORTAUDIO_INCLUDE_DIRS - ${PORTAUDIO_INCLUDE_DIR} - ) - set(PORTAUDIO_LIBRARIES - ${PORTAUDIO_LIBRARY} - ) - - set(PORTAUDIO_LIBRARY_DIRS - ${PORTAUDIO_LIBRARY_DIR} - ) - - set(PORTAUDIO_VERSION - 18 - ) - - if (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES) - set(PORTAUDIO_FOUND TRUE) - endif (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES) - - if (PORTAUDIO_FOUND) - if (NOT Portaudio_FIND_QUIETLY) - message(STATUS "Found Portaudio: ${PORTAUDIO_LIBRARIES}") - endif (NOT Portaudio_FIND_QUIETLY) - else (PORTAUDIO_FOUND) - if (Portaudio_FIND_REQUIRED) - message(FATAL_ERROR "Could not find Portaudio") - endif (Portaudio_FIND_REQUIRED) - endif (PORTAUDIO_FOUND) - endif (PORTAUDIO2_FOUND) - - - # show the PORTAUDIO_INCLUDE_DIRS and PORTAUDIO_LIBRARIES variables only in the advanced view - mark_as_advanced(PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES) - -endif (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS) +include(FindPkgConfig) +pkg_check_modules(PC_PORTAUDIO portaudio) + +find_path(PORTAUDIO_INCLUDE_DIRS + NAMES + portaudio.h + PATHS + /usr/local/include + /usr/include + HINTS + ${PC_PORTAUDIO_INCLUDE_DIR} +) + +find_library(PORTAUDIO_LIBRARIES + NAMES + portaudio + PATHS + /usr/local/lib + /usr/lib + /usr/lib64 + HINTS + ${PC_PORTAUDIO_LIBDIR} +) + +mark_as_advanced(PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PORTAUDIO DEFAULT_MSG PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES) diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake index eff9cbcdc..14f2b29cd 100644 --- a/cmake/Modules/GrPython.cmake +++ b/cmake/Modules/GrPython.cmake @@ -76,12 +76,11 @@ macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) execute_process( COMMAND ${PYTHON_EXECUTABLE} -c " ######################################### -try: import ${mod} -except: - try: ${mod} - except: exit(-1) -try: assert ${cmd} -except: exit(-1) +try: + import ${mod} + assert ${cmd} +except ImportError, AssertionError: exit(-1) +except: pass #########################################" RESULT_VARIABLE ${have} ) diff --git a/docs/doxygen/other/build_guide.dox b/docs/doxygen/other/build_guide.dox index 780976d62..629a0f89f 100644 --- a/docs/doxygen/other/build_guide.dox +++ b/docs/doxygen/other/build_guide.dox @@ -19,13 +19,16 @@ components is determined by what the user requires from GNU Radio. If, for example, you do not use any Comedi-based hardware, do not worry about building gr-comedi. +Before trying to build these from source, please try your system's +installation tool (apt-get, pkg_install, YaST, yum, urpmi, etc.) +first. Most recent systems have these packages available. + \subsection dep_global Global Dependencies \li git http://code.google.com/p/msysgit \li cmake (>= 2.6) http://www.cmake.org/cmake/resources/software.html \li boost (>= 1.35) http://www.boostpro.com/download \li cppunit (>= 1.9.14) http://gaiacrtn.free.fr/cppunit/index.html \li fftw3f (>= 3.0) http://www.fftw.org/install/windows.html -\li gsl (>= 1.10) http://gnuwin32.sourceforge.net/packages/gsl.htm \subsection dep_python Python Wrappers \li python (>= 2.5) http://www.python.org/download/ @@ -39,6 +42,9 @@ about building gr-comedi. \li Cheetah (>= 2.0) http://www.cheetahtemplate.org/ \li pygtk (>= 2.10) http://www.pygtk.org/downloads.html +\subsection dep_wavelet gr-wavelet: Collection of wavelet blocks +\li gsl (>= 1.10) http://gnuwin32.sourceforge.net/packages/gsl.htm + \subsection dep_gr_qtgui gr-qtgui: The QT-based Graphical User Interface \li qt (>= 4.4) http://qt.nokia.com/downloads/ \li qwt (>= 5.2) http://sourceforge.net/projects/qwt/ @@ -57,6 +63,10 @@ about building gr-comedi. \li audio-osx \li audio-windows +It is not necessary to satisfy all of these dependencies; just the +one(s) that are right for your system. On Linux, don't expect +audio-osx and audio-windows to be either satisfied or built. + \subsection dep_uhd uhd: The Ettus USRP Hardware Driver Interface \li uhd (>= 3.0.0) http://code.ettus.com/redmine/ettus/projects/uhd/wiki @@ -146,23 +156,3 @@ cmake -DCMAKE_CXX_FLAGS:STRING="-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -g -DCMAKE_C_FLAGS:STRING="-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -g" \ <gr_source_dir> \endcode - - -\section build_old_autotools Building Using Old Autotools Method - -As of version 3.5, we have moved to using Cmake as the default, -preferred build system. If for some reason, Cmake fails on your -system, GNU Radio still includes the old autotools build process as a -parallel build method. To build: - -\code -$ cd $(srcdir) -$ ./bootstrap // only if not building from a tarball -$ cd $(builddir) -$ $(srcdir)/configure [options] -$ make [-jN] -$ make check -$ sudo make install -\endcode - -*/ diff --git a/gnuradio-core/src/lib/filter/CMakeLists.txt b/gnuradio-core/src/lib/filter/CMakeLists.txt index 02a72191c..facaff764 100644 --- a/gnuradio-core/src/lib/filter/CMakeLists.txt +++ b/gnuradio-core/src/lib/filter/CMakeLists.txt @@ -195,6 +195,9 @@ elseif(CMAKE_SYSTEM_PROCESSOR_x86 AND "${CMAKE_SYSTEM_PROCESSOR_x86}" STREQUAL " ${CMAKE_CURRENT_SOURCE_DIR}/short_dotprod_mmx.S ) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-maltivec) + endif() list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/sysconfig_powerpc.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_sysconfig_powerpc.cc diff --git a/gnuradio-core/src/lib/swig/gnuradio.i b/gnuradio-core/src/lib/swig/gnuradio.i index 239223851..3a421ad5d 100644 --- a/gnuradio-core/src/lib/swig/gnuradio.i +++ b/gnuradio-core/src/lib/swig/gnuradio.i @@ -20,6 +20,9 @@ * Boston, MA 02110-1301, USA. */ +// Disable warning about base class types +#pragma SWIG nowarn=401 + //////////////////////////////////////////////////////////////////////// // gnuradio.i // SWIG interface definition diff --git a/gnuradio-core/src/lib/swig/gr_swig_block_magic.i b/gnuradio-core/src/lib/swig/gr_swig_block_magic.i index cdc9fbe49..4016ae772 100644 --- a/gnuradio-core/src/lib/swig/gr_swig_block_magic.i +++ b/gnuradio-core/src/lib/swig/gr_swig_block_magic.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2010 Free Software Foundation, Inc. + * Copyright 2004,2010,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -40,3 +40,11 @@ FULL_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), %} %enddef #endif + +%define GR_SWIG_BLOCK_MAGIC2(PKG, BASE_NAME) +%template(BASE_NAME ## _sptr) boost::shared_ptr<gr:: ## PKG ## :: ## BASE_NAME>; +%pythoncode %{ +BASE_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id()) +BASE_NAME = BASE_NAME.make; +%} +%enddef diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_dc_blocker.py b/gnuradio-core/src/python/gnuradio/gr/qa_dc_blocker.py index 0f6fa86f5..175735867 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_dc_blocker.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_dc_blocker.py @@ -46,7 +46,7 @@ class test_dc_blocker(gr_unittest.TestCase): # only test samples around 2D-2 result_data = dst.data()[60:65] - self.assertFloatTuplesAlmostEqual (expected_result, result_data) + self.assertComplexTuplesAlmostEqual (expected_result, result_data) def test_002(self): ''' Test impulse response - short form, cc ''' @@ -64,7 +64,7 @@ class test_dc_blocker(gr_unittest.TestCase): # only test samples around D-1 result_data = dst.data()[29:34] - self.assertFloatTuplesAlmostEqual (expected_result, result_data) + self.assertComplexTuplesAlmostEqual (expected_result, result_data) def test_003(self): diff --git a/gr-digital/examples/narrowband/digital_bert_rx.py b/gr-digital/examples/narrowband/digital_bert_rx.py index cc12b71b2..ab7e988eb 100755 --- a/gr-digital/examples/narrowband/digital_bert_rx.py +++ b/gr-digital/examples/narrowband/digital_bert_rx.py @@ -70,7 +70,7 @@ class bert_receiver(gr.hier_block2): freq_bw, timing_bw, phase_bw, verbose, log) - self._symbol_rate = self._bitrate * self._demod.bits_per_symbol() + self._symbol_rate = self._bitrate / self._demod.bits_per_symbol() self._sample_rate = self._symbol_rate * samples_per_symbol # Add an SNR probe on the demodulated constellation diff --git a/gr-digital/python/qa_fll_band_edge.py b/gr-digital/python/qa_fll_band_edge.py index 7d89bc9ea..9e4ca079b 100755 --- a/gr-digital/python/qa_fll_band_edge.py +++ b/gr-digital/python/qa_fll_band_edge.py @@ -78,7 +78,7 @@ class test_fll_band_edge_cc(gr_unittest.TestCase): dst_data = self.vsnk_frq.data()[N:] expected_result = len(dst_data)* [-0.20,] - self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 4) if __name__ == '__main__': gr_unittest.run(test_fll_band_edge_cc, "test_fll_band_edge_cc.xml") diff --git a/gr-fcd/grc/fcd_source_c.xml b/gr-fcd/grc/fcd_source_c.xml index 7c55239aa..1b83cba7f 100644 --- a/gr-fcd/grc/fcd_source_c.xml +++ b/gr-fcd/grc/fcd_source_c.xml @@ -19,7 +19,7 @@ self.$(id).set_freq_corr($ppm) self.$(id).set_dc_corr($dci,$dcq) #end if #if ($iq_phase() != 0.0) or ($iq_gain() != 1.0) -self.$(id).set_iq_corr($iq_phase,$iq_gain) +self.$(id).set_iq_corr($iq_gain,$iq_phase) #end if self.$(id).set_freq($freq) </make> diff --git a/gr-fcd/lib/CMakeLists.txt b/gr-fcd/lib/CMakeLists.txt index cfca8b81b..9a5605d99 100644 --- a/gr-fcd/lib/CMakeLists.txt +++ b/gr-fcd/lib/CMakeLists.txt @@ -63,5 +63,10 @@ endif() add_library(gnuradio-fcd SHARED ${gr_fcd_sources}) +if (LINUX) + list(APPEND fcd_libs rt) +endif() target_link_libraries(gnuradio-fcd ${fcd_libs}) + + GR_LIBRARY_FOO(gnuradio-fcd RUNTIME_COMPONENT "fcd_runtime" DEVEL_COMPONENT "fcd_devel") diff --git a/gr-fft/CMakeLists.txt b/gr-fft/CMakeLists.txt new file mode 100644 index 000000000..9ee338341 --- /dev/null +++ b/gr-fft/CMakeLists.txt @@ -0,0 +1,111 @@ +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Setup dependencies +######################################################################## +include(GrBoost) + +find_package(FFTW3f) + +######################################################################## +# Register component +######################################################################## +include(GrComponent) + +GR_REGISTER_COMPONENT("gr-fft" ENABLE_GR_FFT + ENABLE_GRUEL + ENABLE_VOLK + Boost_FOUND + ENABLE_GR_CORE + FFTW3F_FOUND +) + +GR_SET_GLOBAL(GR_FFT_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/lib + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +######################################################################## +# Begin conditional configuration +######################################################################## +if(ENABLE_GR_FFT) + +######################################################################## +# Setup CPack components +######################################################################## +include(GrPackage) +CPACK_SET(CPACK_COMPONENT_GROUP_FFT_DESCRIPTION "GNU Radio FFT Blocks") + +CPACK_COMPONENT("fft_runtime" + GROUP "FFT" + DISPLAY_NAME "Runtime" + DESCRIPTION "Runtime" + DEPENDS "core_runtime" +) + +CPACK_COMPONENT("fft_devel" + GROUP "FFT" + DISPLAY_NAME "Development" + DESCRIPTION "C++ headers, package config, import libraries" + DEPENDS "core_devel" +) + +CPACK_COMPONENT("fft_python" + GROUP "FFT" + DISPLAY_NAME "Python" + DESCRIPTION "Python modules for runtime; GRC xml files" + DEPENDS "core_python;fft_runtime" +) + +CPACK_COMPONENT("fft_swig" + GROUP "FFT" + DISPLAY_NAME "SWIG" + DESCRIPTION "SWIG development .i files" + DEPENDS "core_swig;fft_python;fft_devel" +) + +######################################################################## +# Add subdirectories +######################################################################## +add_subdirectory(include/fft) +add_subdirectory(lib) +if(ENABLE_PYTHON) + add_subdirectory(swig) + add_subdirectory(python) +# add_subdirectory(grc) +endif(ENABLE_PYTHON) +#add_subdirectory(examples) +#add_subdirectory(doc) + +######################################################################## +# Create Pkg Config File +######################################################################## +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-fft.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-fft.pc +@ONLY) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-fft.pc + DESTINATION ${GR_LIBRARY_DIR}/pkgconfig + COMPONENT "fft_devel" +) + +endif(ENABLE_GR_FFT) diff --git a/gr-fft/doc/CMakeLists.txt b/gr-fft/doc/CMakeLists.txt new file mode 100644 index 000000000..96c42f030 --- /dev/null +++ b/gr-fft/doc/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install( + FILES README.fft + DESTINATION ${GR_PKG_DOC_DIR} +) diff --git a/gr-fft/doc/README.fft b/gr-fft/doc/README.fft new file mode 100644 index 000000000..3ea9e81f8 --- /dev/null +++ b/gr-fft/doc/README.fft @@ -0,0 +1,13 @@ +This is the gr-fft package. It contains signal processing blocks to +perform FFTs and FFT-related functionality. + +The Python namespace is in gnuradio.fft, which would be normally +imported as: + + from gnuradio import fft + +See the Doxygen documentation for details about the blocks available +in this package. A quick listing of the details can be found in Python +after importing by using: + + help(fft) diff --git a/gr-fft/doc/fft.dox b/gr-fft/doc/fft.dox new file mode 100644 index 000000000..5bf612d84 --- /dev/null +++ b/gr-fft/doc/fft.dox @@ -0,0 +1,29 @@ +/*! \page page_fft FFT Signal Processing Blocks + +\section Introduction + +This is the gr-fft package. It contains signal processing blocks to +perform FFTs and FFT-related functionality. + +The Python namespace is in gnuradio.fft, which would be normally +imported as: + +\code + from gnuradio import fft +\endcode + +See the Doxygen documentation for details about the blocks available +in this package. A quick listing of the details can be found in Python +after importing by using: + +\code + help(fft) +\endcode + +\section Dependencies + +The FFT blocks require the following dependencies. + +\li fftw3f (>= 3.0) http://www.fftw.org/download.html + +*/ diff --git a/gr-fft/gnuradio-fft.pc.in b/gr-fft/gnuradio-fft.pc.in new file mode 100644 index 000000000..eb4ddfd9f --- /dev/null +++ b/gr-fft/gnuradio-fft.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnuradio-fft +Description: GNU Radio's FFT signal processing blocks +Requires: gnuradio-core +Version: @LIBVER@ +Libs: -L${libdir} -lgnuradio-fft +Cflags: -I${includedir} diff --git a/gr-fft/grc/CMakeLists.txt b/gr-fft/grc/CMakeLists.txt new file mode 100644 index 000000000..632a9aaad --- /dev/null +++ b/gr-fft/grc/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + fft_block_tree.xml + fft_vxx.xml + goertzel_fc.xml + DESTINATION ${GRC_BLOCKS_DIR} + COMPONENT "fft_python" +) diff --git a/gr-fft/grc/fft_block_tree.xml b/gr-fft/grc/fft_block_tree.xml new file mode 100644 index 000000000..3bda77eae --- /dev/null +++ b/gr-fft/grc/fft_block_tree.xml @@ -0,0 +1,36 @@ +<?xml version="1.0"?> + +<!-- + Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, + Boston, MA 02110-1301, USA. +--> + +<!-- +################################################### +##Block Tree for GR FFT blocks. +################################################### + --> +<cat> + <name></name> <!-- Blank for Root Name --> + <cat> + <name>FFT</name> + <block>fft_vxx</block> + <block>goertzel_fc</block> + </cat> +</cat> diff --git a/gr-fft/grc/fft_vxx.xml b/gr-fft/grc/fft_vxx.xml new file mode 100644 index 000000000..69f12ace7 --- /dev/null +++ b/gr-fft/grc/fft_vxx.xml @@ -0,0 +1,88 @@ +<?xml version="1.0"?> +<!-- +################################################### +##FFT +################################################### + --> +<block> + <name>FFT</name> + <key>fft_vxx</key> + <import>from gnuradio import fft</import> + <import>from gnuradio import window</import> + <make>#if $type() == "complex" +fft.fft_vcc($fft_size, $forward, $window, $shift, $nthreads) +#else +fft.fft_vfc($fft_size, $forward, $window, $nthreads) +#end if</make> + <callback>set_nthreads($nthreads)</callback> + <param> + <name>Input Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>hide_shift:</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>hide_shift:all</opt> + </option> + </param> + <param> + <name>FFT Size</name> + <key>fft_size</key> + <value>1024</value> + <type>int</type> + </param> + <param> + <name>Forward/Reverse</name> + <key>forward</key> + <type>enum</type> + <option> + <name>Forward</name> + <key>True</key> + </option> + <option> + <name>Reverse</name> + <key>False</key> + </option> + </param> + <param> + <name>Window</name> + <key>window</key> + <value>window.blackmanharris(1024)</value> + <type>real_vector</type> + </param> + <param> + <name>Shift</name> + <key>shift</key> + <type>enum</type> + <hide>$type.hide_shift</hide> + <option> + <name>Yes</name> + <key>True</key> + </option> + <option> + <name>No</name> + <key>False</key> + </option> + </param> + <param> + <name>Num. Threads</name> + <key>nthreads</key> + <value>1</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>$type</type> + <vlen>$fft_size</vlen> + </sink> + <source> + <name>out</name> + <type>complex</type> + <vlen>$fft_size</vlen> + </source> +</block> diff --git a/gr-fft/grc/goertzel_fc.xml b/gr-fft/grc/goertzel_fc.xml new file mode 100644 index 000000000..371284358 --- /dev/null +++ b/gr-fft/grc/goertzel_fc.xml @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Goertzel +################################################### + --> +<block> + <name>Goertzel</name> + <key>goertzel_fc</key> + <import>from gnuradio import fft</import> + <make>fft.goertzel_fc($rate, $len, $freq)</make> + <callback>set_freq($freq)</callback> + <callback>set_rate($rate)</callback> + <param> + <name>Rate</name> + <key>rate</key> + <type>int</type> + </param> + <param> + <name>Length</name> + <key>len</key> + <type>int</type> + </param> + <param> + <name>Frequency</name> + <key>freq</key> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>float</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-fft/include/fft/CMakeLists.txt b/gr-fft/include/fft/CMakeLists.txt new file mode 100644 index 000000000..bce3da674 --- /dev/null +++ b/gr-fft/include/fft/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Install header files +######################################################################## +install(FILES + api.h + fft.h + fft_vcc.h + fft_vfc.h + goertzel.h + goertzel_fc.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/fft + COMPONENT "fft_devel" +) + diff --git a/gr-fft/include/fft/api.h b/gr-fft/include/fft/api.h new file mode 100644 index 000000000..eef456373 --- /dev/null +++ b/gr-fft/include/fft/api.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_API_H +#define INCLUDED_FFT_API_H + +#include <gruel/attributes.h> + +#ifdef gnuradio_fft_EXPORTS +# define FFT_API __GR_ATTR_EXPORT +#else +# define FFT_API __GR_ATTR_IMPORT +#endif + +#endif /* INCLUDED_FFT_API_H */ diff --git a/gr-fft/include/fft/fft.h b/gr-fft/include/fft/fft.h new file mode 100644 index 000000000..5cc2e21e8 --- /dev/null +++ b/gr-fft/include/fft/fft.h @@ -0,0 +1,195 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2008,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _FFT_FFT_H_ +#define _FFT_FFT_H_ + +/* + * Wrappers for FFTW single precision 1d dft + */ + +#include <fft/api.h> +#include <gr_complex.h> +#include <boost/thread.hpp> + +namespace gr { + namespace fft { + + + /*! \brief Helper function for allocating complex fft buffers + */ + gr_complex* malloc_complex(int size); + + /*! \brief Helper function for allocating float fft buffers + */ + float* malloc_float(int size); + + /*! \brief Helper function for freeing fft buffers + */ + void free(void *b); + + /*! + * \brief Export reference to planner mutex for those apps that + * want to use FFTW w/o using the fft_impl_fftw* classes. + */ + class FFT_API planner { + public: + typedef boost::mutex::scoped_lock scoped_lock; + /*! + * Return reference to planner mutex + */ + static boost::mutex &mutex(); + }; + + /*! + * \brief FFT: complex in, complex out + * \ingroup misc + */ + class FFT_API fft_complex { + int d_fft_size; + int d_nthreads; + gr_complex *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + + public: + fft_complex(int fft_size, bool forward = true, int nthreads=1); + virtual ~fft_complex(); + + /* + * These return pointers to buffers owned by fft_impl_fft_complex + * into which input and output take place. It's done this way in + * order to ensure optimal alignment for SIMD instructions. + */ + gr_complex *get_inbuf() const { return d_inbuf; } + gr_complex *get_outbuf() const { return d_outbuf; } + + int inbuf_length() const { return d_fft_size; } + int outbuf_length() const { return d_fft_size; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in + * outbuf. + */ + void execute(); + }; + + /*! + * \brief FFT: real in, complex out + * \ingroup misc + */ + class FFT_API fft_real_fwd { + int d_fft_size; + int d_nthreads; + float *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + + public: + fft_real_fwd (int fft_size, int nthreads=1); + virtual ~fft_real_fwd (); + + /* + * These return pointers to buffers owned by fft_impl_fft_real_fwd + * into which input and output take place. It's done this way in + * order to ensure optimal alignment for SIMD instructions. + */ + float *get_inbuf() const { return d_inbuf; } + gr_complex *get_outbuf() const { return d_outbuf; } + + int inbuf_length() const { return d_fft_size; } + int outbuf_length() const { return d_fft_size / 2 + 1; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in + * outbuf. + */ + void execute(); + }; + + /*! + * \brief FFT: complex in, float out + * \ingroup misc + */ + class FFT_API fft_real_rev { + int d_fft_size; + int d_nthreads; + gr_complex *d_inbuf; + float *d_outbuf; + void *d_plan; + + public: + fft_real_rev(int fft_size, int nthreads=1); + virtual ~fft_real_rev(); + + /* + * These return pointers to buffers owned by fft_impl_fft_real_rev + * into which input and output take place. It's done this way in + * order to ensure optimal alignment for SIMD instructions. + */ + gr_complex *get_inbuf() const { return d_inbuf; } + float *get_outbuf() const { return d_outbuf; } + + int inbuf_length() const { return d_fft_size / 2 + 1; } + int outbuf_length() const { return d_fft_size; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in + * outbuf. + */ + void execute(); + }; + + } /* namespace fft */ +} /*namespace gr */ + +#endif /* _FFT_FFT_H_ */ diff --git a/gr-fft/include/fft/fft_vcc.h b/gr-fft/include/fft/fft_vcc.h new file mode 100644 index 000000000..561ae858d --- /dev/null +++ b/gr-fft/include/fft/fft_vcc.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2008,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_FFT_VCC_H +#define INCLUDED_FFT_FFT_VCC_H + +#include <fft/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vcc : virtual public gr_sync_block + { + public: + + // gr::fft::fft_vcc::sptr + typedef boost::shared_ptr<fft_vcc> sptr; + + /*! + * \brief Compute forward or reverse FFT. complex vector in / complex vector out. + * \ingroup dft_blk + */ + static FFT_API sptr make(int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); + + virtual void set_nthreads(int n) = 0; + + virtual int nthreads() const = 0; + + virtual bool set_window(const std::vector<float> &window) = 0; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VCC_H */ diff --git a/gr-fft/include/fft/fft_vfc.h b/gr-fft/include/fft/fft_vfc.h new file mode 100644 index 000000000..fc48ceefe --- /dev/null +++ b/gr-fft/include/fft/fft_vfc.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_FFT_VFC_H +#define INCLUDED_FFT_FFT_VFC_H + +#include <fft/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vfc : virtual public gr_sync_block + { + public: + + // gr::fft::fft_vfc::sptr + typedef boost::shared_ptr<fft_vfc> sptr; + + /*! + * \brief Compute forward or reverse FFT. float vector in / complex vector out. + * \ingroup dft_blk + */ + static FFT_API sptr make(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1); + + virtual void set_nthreads(int n) = 0; + + virtual int nthreads() const = 0; + + virtual bool set_window(const std::vector<float> &window) = 0; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VFC_H */ diff --git a/gr-fft/include/fft/goertzel.h b/gr-fft/include/fft/goertzel.h new file mode 100644 index 000000000..ff37355e6 --- /dev/null +++ b/gr-fft/include/fft/goertzel.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2011,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_IMPL_GOERTZEL_H +#define INCLUDED_FFT_IMPL_GOERTZEL_H + +#include <fft/api.h> +#include <gr_types.h> + +namespace gr { + namespace fft { + + /*! + * \brief Implements Goertzel single-bin DFT calculation + * \ingroup misc + */ + class FFT_API goertzel + { + public: + goertzel(){} + goertzel(int rate, int len, float freq); + + void set_params(int rate, int len, float freq); + + // Process a input array + gr_complex batch(float *in); + + // Process sample by sample + void input(const float &in); + gr_complex output(); + bool ready() const { return d_processed == d_len; } + + private: + float d_d1; + float d_d2; + float d_wr; + float d_wi; + int d_len; + int d_processed; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_IMPL_GOERTZEL_H */ diff --git a/gr-fft/include/fft/goertzel_fc.h b/gr-fft/include/fft/goertzel_fc.h new file mode 100644 index 000000000..4d3fa8dcf --- /dev/null +++ b/gr-fft/include/fft/goertzel_fc.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2011,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_GOERTZEL_FC_H +#define INCLUDED_FFT_GOERTZEL_FC_H + +#include <fft/api.h> +#include <gr_sync_decimator.h> + +namespace gr { + namespace fft { + + class FFT_API goertzel_fc : virtual public gr_sync_decimator + { + public: + + // gr::fft::goertzel_fc::sptr + typedef boost::shared_ptr<goertzel_fc> sptr; + + /*! + * \brief Goertzel single-bin DFT calculation. + * \ingroup dft_blk + */ + static FFT_API sptr make(int rate, int len, float freq); + + virtual void set_freq (float freq) = 0; + + virtual void set_rate (int rate) = 0; + + virtual float freq() = 0; + + virtual int rate() = 0; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_GOERTZEL_FC_H */ diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt new file mode 100644 index 000000000..e2f17a183 --- /dev/null +++ b/gr-fft/lib/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Setup the include and linker paths +######################################################################## +include_directories( + ${GNURADIO_CORE_INCLUDE_DIRS} + ${GR_FFT_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +include_directories(${FFT_INCLUDE_DIRS}) +link_directories(${FFT_LIBRARY_DIRS}) + +include_directories(${Boost_INCLUDE_DIRS}) +link_directories(${Boost_LIBRARY_DIRS}) + +include_directories(${FFTW3F_INCLUDE_DIRS}) +link_directories(${FFTW3F_LIBRARY_DIRS}) + +######################################################################## +# Setup library +######################################################################## +list(APPEND fft_sources + fft.cc + fft_vcc_fftw.cc + fft_vfc_fftw.cc + goertzel_fc_impl.cc + goertzel.cc +) + +list(APPEND fft_libs + gnuradio-core + ${Boost_LIBRARIES} + ${FFT_LIBRARIES} + ${FFTW3F_LIBRARIES} +) + +add_library(gnuradio-fft SHARED ${fft_sources}) +target_link_libraries(gnuradio-fft ${fft_libs}) +GR_LIBRARY_FOO(gnuradio-fft RUNTIME_COMPONENT "fft_runtime" DEVEL_COMPONENT "fft_devel") diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc new file mode 100644 index 000000000..6074236e1 --- /dev/null +++ b/gr-fft/lib/fft.cc @@ -0,0 +1,338 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2008,2011,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <fft/fft.h> +#include <gr_sys_paths.h> +#include <fftw3.h> + +#ifdef _MSC_VER //http://www.fftw.org/install/windows.html#DLLwisdom +static void my_fftw_write_char(char c, void *f) { fputc(c, (FILE *) f); } +#define fftw_export_wisdom_to_file(f) fftw_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwf_export_wisdom_to_file(f) fftwf_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwl_export_wisdom_to_file(f) fftwl_export_wisdom(my_fftw_write_char, (void*) (f)) + +static int my_fftw_read_char(void *f) { return fgetc((FILE *) f); } +#define fftw_import_wisdom_from_file(f) fftw_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwf_import_wisdom_from_file(f) fftwf_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwl_import_wisdom_from_file(f) fftwl_import_wisdom(my_fftw_read_char, (void*) (f)) +#endif //_MSC_VER + +#include <gr_complex.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <cassert> +#include <stdexcept> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +namespace fs = boost::filesystem; + +namespace gr { + namespace fft { + + gr_complex * + malloc_complex(int size) + { + return (gr_complex*)fftwf_malloc(sizeof(gr_complex)*size); + } + + float * + malloc_float(int size) + { + return (float*)fftwf_malloc(sizeof(float)*size); + } + + void + free(void *b) + { + fftwf_free(b); + } + + boost::mutex & + planner::mutex() + { + static boost::mutex s_planning_mutex; + + return s_planning_mutex; + } + + static const char * + wisdom_filename() + { + static fs::path path; + path = fs::path(gr_appdata_path()) / ".gr_fftw_wisdom"; + return path.string().c_str(); + } + + static void + import_wisdom() + { + const char *filename = wisdom_filename (); + FILE *fp = fopen (filename, "r"); + if (fp != 0){ + int r = fftwf_import_wisdom_from_file (fp); + fclose (fp); + if (!r){ + fprintf (stderr, "gr::fft: can't import wisdom from %s\n", filename); + } + } + } + + static void + config_threading(int nthreads) + { + static int fftw_threads_inited = 0; + +#ifdef FFTW3F_THREADS + if (fftw_threads_inited == 0) + { + fftw_threads_inited = 1; + fftwf_init_threads(); + } + + fftwf_plan_with_nthreads(nthreads); +#endif + } + + static void + export_wisdom() + { + const char *filename = wisdom_filename (); + FILE *fp = fopen (filename, "w"); + if (fp != 0){ + fftwf_export_wisdom_to_file (fp); + fclose (fp); + } + else { + fprintf (stderr, "fft_impl_fftw: "); + perror (filename); + } + } + +// ---------------------------------------------------------------- + + fft_complex::fft_complex(int fft_size, bool forward, int nthreads) + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("fft_impl_fftw: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + config_threading(nthreads); + import_wisdom(); // load prior wisdom from disk + + d_plan = fftwf_plan_dft_1d (fft_size, + reinterpret_cast<fftwf_complex *>(d_inbuf), + reinterpret_cast<fftwf_complex *>(d_outbuf), + forward ? FFTW_FORWARD : FFTW_BACKWARD, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gr::fft: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_1d failed"); + } + export_wisdom(); // store new wisdom to disk + } + + fft_complex::~fft_complex() + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); + } + + void + fft_complex::set_nthreads(int n) + { + if (n <= 0) + throw std::out_of_range ("gr::fft: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif + } + + void + fft_complex::execute() + { + fftwf_execute((fftwf_plan) d_plan); + } + +// ---------------------------------------------------------------- + + fft_real_fwd::fft_real_fwd (int fft_size, int nthreads) + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gr::fft: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (float *) fftwf_malloc (sizeof (float) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + config_threading(nthreads); + import_wisdom(); // load prior wisdom from disk + + d_plan = fftwf_plan_dft_r2c_1d (fft_size, + d_inbuf, + reinterpret_cast<fftwf_complex *>(d_outbuf), + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gr::fft::fft_real_fwd: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_r2c_1d failed"); + } + export_wisdom(); // store new wisdom to disk + } + + fft_real_fwd::~fft_real_fwd() + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); + } + + void + fft_real_fwd::set_nthreads(int n) + { + if (n <= 0) + throw std::out_of_range ("gr::fft::fft_real_fwd::set_nthreads: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif + } + + void + fft_real_fwd::execute() + { + fftwf_execute ((fftwf_plan) d_plan); + } + + // ---------------------------------------------------------------- + + fft_real_rev::fft_real_rev(int fft_size, int nthreads) + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gr::fft::fft_real_rev: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (float *) fftwf_malloc (sizeof (float) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + config_threading(nthreads); + import_wisdom(); // load prior wisdom from disk + + // FIXME If there's ever a chance that the planning functions + // will be called in multiple threads, we've got to ensure single + // threaded access. They are not thread-safe. + d_plan = fftwf_plan_dft_c2r_1d (fft_size, + reinterpret_cast<fftwf_complex *>(d_inbuf), + d_outbuf, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gr::fft::fft_real_rev: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_c2r_1d failed"); + } + export_wisdom (); // store new wisdom to disk + } + + fft_real_rev::~fft_real_rev () + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); + } + + void + fft_real_rev::set_nthreads(int n) + { + if (n <= 0) + throw std::out_of_range ("gr::fft::fft_real_rev::set_nthreads: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif + } + + void + fft_real_rev::execute () + { + fftwf_execute ((fftwf_plan) d_plan); + } + + } /* namespace fft */ +} /* namespace gr */ diff --git a/gr-fft/lib/fft_vcc_fftw.cc b/gr-fft/lib/fft_vcc_fftw.cc new file mode 100644 index 000000000..ebcd5ec53 --- /dev/null +++ b/gr-fft/lib/fft_vcc_fftw.cc @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2008,2010,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "fft_vcc_fftw.h" +#include <gr_io_signature.h> +#include <math.h> +#include <string.h> + +namespace gr { + namespace fft { + + fft_vcc::sptr fft_vcc::make(int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) + { + return gnuradio::get_initial_sptr(new fft_vcc_fftw + (fft_size, forward, window, + shift, nthreads)); + } + + fft_vcc_fftw::fft_vcc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) + : gr_sync_block("fft_vcc_fftw", + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex)), + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex))), + d_fft_size(fft_size), d_forward(forward), d_shift(shift) + { + d_fft = new fft_complex(d_fft_size, forward, nthreads); + } + + fft_vcc_fftw::~fft_vcc_fftw() + { + delete d_fft; + } + + void + fft_vcc_fftw::set_nthreads(int n) + { + d_fft->set_nthreads(n); + } + + int + fft_vcc_fftw::nthreads() const + { + return d_fft->nthreads(); + } + + bool + fft_vcc_fftw::set_window(const std::vector<float> &window) + { + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; + } + + int + fft_vcc_fftw::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + unsigned int input_data_size = input_signature()->sizeof_stream_item (0); + unsigned int output_data_size = output_signature()->sizeof_stream_item (0); + + int count = 0; + + while(count++ < noutput_items) { + + // copy input into optimally aligned buffer + if(d_window.size()) { + gr_complex *dst = d_fft->get_inbuf(); + if(!d_forward && d_shift) { + unsigned int offset = (!d_forward && d_shift)?(d_fft_size/2):0; + int fft_m_offset = d_fft_size - offset; + for(unsigned int i = 0; i < offset; i++) // apply window + dst[i+fft_m_offset] = in[i] * d_window[i]; + for(unsigned int i = offset; i < d_fft_size; i++) // apply window + dst[i-offset] = in[i] * d_window[i]; + } + else { + for(unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + } + else { + if(!d_forward && d_shift) { // apply an ifft shift on the data + gr_complex *dst = d_fft->get_inbuf(); + unsigned int len = (unsigned int)(floor(d_fft_size/2.0)); // half length of complex array + memcpy(&dst[0], &in[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&dst[d_fft_size - len], &in[0], sizeof(gr_complex)*len); + } + else { + memcpy(d_fft->get_inbuf(), in, input_data_size); + } + } + + // compute the fft + d_fft->execute(); + + // copy result to our output + if(d_forward && d_shift) { // apply a fft shift on the data + unsigned int len = (unsigned int)(ceil(d_fft_size/2.0)); + memcpy(&out[0], &d_fft->get_outbuf()[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&out[d_fft_size - len], &d_fft->get_outbuf()[0], sizeof(gr_complex)*len); + } + else { + memcpy (out, d_fft->get_outbuf (), output_data_size); + } + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; + } + + } /* namespace fft */ +} /* namespace gr */ diff --git a/gr-fft/lib/fft_vcc_fftw.h b/gr-fft/lib/fft_vcc_fftw.h new file mode 100644 index 000000000..ea15dd07b --- /dev/null +++ b/gr-fft/lib/fft_vcc_fftw.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2008,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H +#define INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H + +#include <fft/fft_vcc.h> +#include <fft/fft.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vcc_fftw : public fft_vcc + { + private: + fft_complex *d_fft; + unsigned int d_fft_size; + std::vector<float> d_window; + bool d_forward; + bool d_shift; + + public: + fft_vcc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads=1); + + ~fft_vcc_fftw(); + + void set_nthreads(int n); + int nthreads() const; + bool set_window(const std::vector<float> &window); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H */ diff --git a/gr-fft/lib/fft_vfc_fftw.cc b/gr-fft/lib/fft_vfc_fftw.cc new file mode 100644 index 000000000..8f9b127e5 --- /dev/null +++ b/gr-fft/lib/fft_vfc_fftw.cc @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2008,2010,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "fft_vfc_fftw.h" +#include <gr_io_signature.h> +#include <math.h> +#include <string.h> + +namespace gr { + namespace fft { + + fft_vfc::sptr fft_vfc::make(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads) + { + return gnuradio::get_initial_sptr(new fft_vfc_fftw + (fft_size, forward, window, + nthreads)); + } + + fft_vfc_fftw::fft_vfc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads) + : gr_sync_block("fft_vfc_fftw", + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex)), + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex))), + d_fft_size(fft_size), d_forward(forward) + { + d_fft = new fft_complex(d_fft_size, forward, nthreads); + } + + fft_vfc_fftw::~fft_vfc_fftw() + { + delete d_fft; + } + + void + fft_vfc_fftw::set_nthreads(int n) + { + d_fft->set_nthreads(n); + } + + int + fft_vfc_fftw::nthreads() const + { + return d_fft->nthreads(); + } + + bool + fft_vfc_fftw::set_window(const std::vector<float> &window) + { + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; + } + + int + fft_vfc_fftw::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + unsigned int output_data_size = output_signature()->sizeof_stream_item (0); + + int count = 0; + + while(count++ < noutput_items) { + + // copy input into optimally aligned buffer + if(d_window.size()) { + gr_complex *dst = d_fft->get_inbuf(); + for(unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + else { + gr_complex *dst = d_fft->get_inbuf(); + for(unsigned int i = 0; i < d_fft_size; i++) // float to complex conversion + dst[i] = in[i]; + } + + // compute the fft + d_fft->execute(); + + // copy result to output stream + memcpy(out, d_fft->get_outbuf(), output_data_size); + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; + } + + } /* namespace fft */ +} /* namespace gr */ + diff --git a/gr-fft/lib/fft_vfc_fftw.h b/gr-fft/lib/fft_vfc_fftw.h new file mode 100644 index 000000000..1b6f78ba6 --- /dev/null +++ b/gr-fft/lib/fft_vfc_fftw.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2008,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H +#define INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H + +#include <fft/fft_vfc.h> +#include <fft/fft.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vfc_fftw : public fft_vfc + { + private: + fft_complex *d_fft; + unsigned int d_fft_size; + std::vector<float> d_window; + bool d_forward; + + public: + fft_vfc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1); + + ~fft_vfc_fftw(); + + void set_nthreads(int n); + int nthreads() const; + bool set_window(const std::vector<float> &window); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H */ diff --git a/gr-fft/lib/goertzel.cc b/gr-fft/lib/goertzel.cc new file mode 100644 index 000000000..4bcd5ee19 --- /dev/null +++ b/gr-fft/lib/goertzel.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2011,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <cmath> +#include <fft/goertzel.h> + +namespace gr { + namespace fft { + + goertzel::goertzel(int rate, int len, float freq) + { + set_params(rate, len, freq); + } + + void + goertzel::set_params(int rate, int len, float freq) + { + d_d1 = 0.0; + d_d2 = 0.0; + + float w = 2.0*M_PI*freq/rate; + d_wr = 2.0*std::cos(w); + d_wi = std::sin(w); + d_len = len; + d_processed = 0; + } + + gr_complex + goertzel::batch(float *in) + { + d_d1 = 0.0; + d_d2 = 0.0; + + for(int i = 0; i < d_len; i++) + input(in[i]); + + return output(); + } + + void + goertzel::input(const float &input) + { + float y = input + d_wr*d_d1 - d_d2; + d_d2 = d_d1; + d_d1 = y; + d_processed++; + } + + gr_complex + goertzel::output() + { + gr_complex out((0.5*d_wr*d_d1-d_d2)/d_len, (d_wi*d_d1)/d_len); + d_d1 = 0.0; + d_d2 = 0.0; + d_processed = 0; + return out; + } + + } /* namespace fft */ +}/* namespace gr */ + diff --git a/gr-fft/lib/goertzel_fc_impl.cc b/gr-fft/lib/goertzel_fc_impl.cc new file mode 100644 index 000000000..ee214f24d --- /dev/null +++ b/gr-fft/lib/goertzel_fc_impl.cc @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2010-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "goertzel_fc_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace fft { + + goertzel_fc::sptr goertzel_fc::make(int rate, int len, float freq) + { + return gnuradio::get_initial_sptr(new goertzel_fc_impl(rate, len, freq)); + } + + goertzel_fc_impl::goertzel_fc_impl(int rate, int len, float freq) + : gr_sync_decimator("goertzel_fc", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + len), + d_goertzel(rate, len, freq) + { + d_len = len; + d_rate = rate; + d_freq = freq; + } + + goertzel_fc_impl::~goertzel_fc_impl() + { + } + + void + goertzel_fc_impl::set_freq(float freq) + { + d_freq = freq; + d_goertzel.set_params(d_rate, d_len, d_freq); + } + + void + goertzel_fc_impl::set_rate(int rate) + { + d_rate = rate; + d_goertzel.set_params(d_rate, d_len, d_freq); + } + + int + goertzel_fc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + float *in = (float *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + for(int i = 0; i < noutput_items; i++) { + *out++ = d_goertzel.batch(in); + in += d_len; + } + + return noutput_items; + } + + } /* namespace fft */ +} /* namespace gr */ diff --git a/gr-fft/lib/goertzel_fc_impl.h b/gr-fft/lib/goertzel_fc_impl.h new file mode 100644 index 000000000..426bc71f6 --- /dev/null +++ b/gr-fft/lib/goertzel_fc_impl.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2011,2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FFT_GOERTZEL_FC_IMPL_H +#define INCLUDED_FFT_GOERTZEL_FC_IMPL_H + +#include <fft/goertzel_fc.h> +#include <fft/goertzel.h> + +namespace gr { + namespace fft { + + class FFT_API goertzel_fc_impl : public goertzel_fc + { + private: + goertzel d_goertzel; + int d_len; + float d_freq; + int d_rate; + + public: + goertzel_fc_impl(int rate, int len, float freq); + + ~goertzel_fc_impl(); + + void set_freq(float freq); + void set_rate(int rate); + + float freq() { return d_freq; } + int rate() { return d_rate; } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_GOERTZEL_FC_IMPL_H */ + diff --git a/gr-fft/python/CMakeLists.txt b/gr-fft/python/CMakeLists.txt new file mode 100644 index 000000000..16c29e599 --- /dev/null +++ b/gr-fft/python/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +include(GrPython) + +GR_PYTHON_INSTALL( + FILES + __init__.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft + COMPONENT "fft_python" +) + +######################################################################## +# Handle the unit tests +######################################################################## +if(ENABLE_TESTING) +include(GrTest) +file(GLOB py_qa_test_files "qa_*.py") +foreach(py_qa_test_file ${py_qa_test_files}) + get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) + set(GR_TEST_PYTHON_DIRS + ${CMAKE_BINARY_DIR}/gnuradio-core/src/python + ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig + ${CMAKE_BINARY_DIR}/gr-fft/python + ${CMAKE_BINARY_DIR}/gr-fft/swig + ) + set(GR_TEST_TARGET_DEPS gruel gnuradio-core gnuradio-fft) + GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${py_qa_test_file}) +endforeach(py_qa_test_file) +endif(ENABLE_TESTING) diff --git a/gr-fft/python/__init__.py b/gr-fft/python/__init__.py new file mode 100644 index 000000000..0fa643e35 --- /dev/null +++ b/gr-fft/python/__init__.py @@ -0,0 +1,28 @@ +# +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +''' +This is the gr-fft package. This package provides GNU Radio +processing blocks for FFT and related functions. +''' + +from fft_swig import * + diff --git a/gr-fft/python/qa_fft.py b/gr-fft/python/qa_fft.py new file mode 100755 index 000000000..1c45ac148 --- /dev/null +++ b/gr-fft/python/qa_fft.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python +# +# Copyright 2008,2010,2012 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. +# + +from gnuradio import gr, gr_unittest +import fft_swig as fft +import sys +import random + +primes = (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53, + 59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131, + 137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223, + 227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311) + + +class test_fft(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def assert_fft_ok2(self, expected_result, result_data): + expected_result = expected_result[:len(result_data)] + self.assertComplexTuplesAlmostEqual2 (expected_result, result_data, + abs_eps=1e-9, rel_eps=4e-4) + + def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4): + expected_result = expected_result[:len(result_data)] + self.assertFloatTuplesAlmostEqual2 (expected_result, result_data, + abs_eps, rel_eps) + + def test_001(self): + tb = gr.top_block() + fft_size = 32 + src_data = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + expected_result = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + op = fft.fft_vcc(fft_size, True, [], False) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, op, v2s, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + self.assert_fft_ok2(expected_result, result_data) + + def test_002(self): + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + op = fft.fft_vcc(fft_size, False, [], False) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, op, v2s, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + self.assert_fft_ok2(expected_result, result_data) + + def test_003(self): + # Same test as above, only use 2 threads + + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + nthreads = 2 + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + op = fft.fft_vcc(fft_size, False, [], False, nthreads) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, op, v2s, dst) + tb.run() + result_data = dst.data() + self.assert_fft_ok2(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_fft, "test_fft.xml") + diff --git a/gr-fft/python/qa_goertzel.py b/gr-fft/python/qa_goertzel.py new file mode 100755 index 000000000..27f9d370e --- /dev/null +++ b/gr-fft/python/qa_goertzel.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2006,2007,2010,2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from math import pi, cos +import fft_swig as fft + +class test_goertzel(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def make_tone_data(self, rate, freq): + return [cos(2*pi*x*freq/rate) for x in range(rate)] + + def transform(self, src_data, rate, freq): + src = gr.vector_source_f(src_data, False) + dft = fft.goertzel_fc(rate, rate, freq) + dst = gr.vector_sink_c() + self.tb.connect(src, dft, dst) + self.tb.run() + return dst.data() + + def test_001(self): # Measure single tone magnitude + rate = 8000 + freq = 100 + bin = freq + src_data = self.make_tone_data(rate, freq) + expected_result = 0.5 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) + + def test_002(self): # Measure off frequency magnitude + rate = 8000 + freq = 100 + bin = freq/2 + src_data = self.make_tone_data(rate, freq) + expected_result = 0.0 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) + +if __name__ == '__main__': + gr_unittest.run(test_goertzel, "test_goertzel.xml") diff --git a/gr-fft/swig/CMakeLists.txt b/gr-fft/swig/CMakeLists.txt new file mode 100644 index 000000000..63f5dfb0e --- /dev/null +++ b/gr-fft/swig/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Setup swig generation +######################################################################## +include(GrPython) +include(GrSwig) + +set(GR_SWIG_INCLUDE_DIRS + ${GR_FFT_INCLUDE_DIRS} + ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} +) + +set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/fft_swig_doc.i) +set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) + +set(GR_SWIG_LIBRARIES gnuradio-fft) + +GR_SWIG_MAKE(fft_swig fft_swig.i) + +GR_SWIG_INSTALL( + TARGETS fft_swig + DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft + COMPONENT "fft_python" +) + +install( + FILES + fft_swig.i + ${CMAKE_CURRENT_BINARY_DIR}/fft_swig_doc.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "fft_swig" +) diff --git a/volk/python/volk_square_ff.i b/gr-fft/swig/fft_swig.i index 5456c81fd..07fab34d4 100644 --- a/volk/python/volk_square_ff.i +++ b/gr-fft/swig/fft_swig.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2010 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -14,24 +14,29 @@ * 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. + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. */ -/* - * First arg is the package prefix. - * Second arg is the name of the class minus the prefix. - * - * This does some behind-the-scenes magic so we can - * access gr_example_square_ff from python as howto.square_ff - */ -GR_SWIG_BLOCK_MAGIC(volk,square_ff); +#define FFT_API + +%include "gnuradio.i" + +//load generated python docstrings +%include "fft_swig_doc.i" + +%{ +#include "fft/fft_vcc.h" +#include "fft/fft_vfc.h" +#include "fft/goertzel_fc.h" +%} -volk_square_ff_sptr volk_make_square_ff (); +%include "fft/fft_vcc.h" +%include "fft/fft_vfc.h" +%include "fft/goertzel_fc.h" -class volk_square_ff : public gr_sync_block -{ -private: - volk_square_ff(); -}; +GR_SWIG_BLOCK_MAGIC2(fft, fft_vcc); +GR_SWIG_BLOCK_MAGIC2(fft, fft_vfc); +GR_SWIG_BLOCK_MAGIC2(fft, goertzel_fc); diff --git a/gr-uhd/apps/uhd_fft b/gr-uhd/apps/uhd_fft index 8bb5e0d2b..7af2c5326 100755 --- a/gr-uhd/apps/uhd_fft +++ b/gr-uhd/apps/uhd_fft @@ -196,18 +196,18 @@ class app_top_block(stdgui2.std_top_block): callback=self.set_gain) try: - mboard_id = self.u.get_usrp_info().get("mboard_id").split(" ")[0] + mboard_id = self.u.get_usrp_info().get("mboard_id") mboard_serial = self.u.get_usrp_info().get("mboard_serial") if mboard_serial == "": mboard_serial = "no serial" - dboard_id = self.u.get_usrp_info().get("rx_id").split(" ")[0].split(",")[0] + dboard_subdev_name = self.u.get_usrp_info().get("rx_subdev_name") dboard_serial = self.u.get_usrp_info().get("rx_serial") if dboard_serial == "": dboard_serial = "no serial" subdev = self.u.get_subdev_spec() antenna = self.u.get_antenna() - usrp_config_val = "%s (%s), %s (%s, %s, %s)" % (mboard_id, mboard_serial, dboard_id, dboard_serial, subdev, antenna) + usrp_config_val = "%s (%s), %s (%s, %s, %s)" % (mboard_id, mboard_serial, dboard_subdev_name, dboard_serial, subdev, antenna) except: usrp_config_val = "Not implemented in this version." diff --git a/gr-uhd/apps/uhd_rx_cfile b/gr-uhd/apps/uhd_rx_cfile index fb639623e..62874771c 100755 --- a/gr-uhd/apps/uhd_rx_cfile +++ b/gr-uhd/apps/uhd_rx_cfile @@ -91,7 +91,27 @@ class rx_cfile_block(gr.top_block): input_rate = self._u.get_samp_rate() if options.verbose: - print "Args: ", options.args + try: + info = self._u.get_usrp_info() + + mboard_id = info.get("mboard_id").split(" ")[0] + if info.get("mboard_serial") == "": + mboard_serial = "no serial" + else: + mboard_serial = info.get("mboard_serial") + + rx_id = info.get("rx_id").split(" ")[0] + if info.get("rx_serial") == "": + rx_serial = "no serial" + else: + rx_serial = info.get("rx_serial") + rx_antenna = info.get("rx_antenna") + rx_subdev_spec = info.get("rx_subdev_spec") + + print "Motherboard: %s (%s)" % (mboard_id, mboard_serial) + print "Daughterboard: %s (%s, %s, %s)" % (rx_id, rx_serial, rx_antenna, rx_subdev_spec) + except: + print "Args: ", options.args print "Rx gain:", options.gain print "Rx baseband frequency:", n2s(tr.actual_rf_freq) print "Rx DDC frequency:", n2s(tr.actual_dsp_freq) diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py index 5fa881e42..8c69da1cc 100644 --- a/gr-uhd/apps/uhd_siggen_base.py +++ b/gr-uhd/apps/uhd_siggen_base.py @@ -110,11 +110,11 @@ class top_block(gr.top_block, pubsub): # Setup USRP Configuration value try: usrp_info = self._u.get_usrp_info() - mboard_id = usrp_info.get("mboard_id").split(" ")[0] + mboard_id = usrp_info.get("mboard_id") mboard_serial = usrp_info.get("mboard_serial") if mboard_serial == "": mboard_serial = "no serial" - dboard_id = usrp_info.get("tx_id").split(" ")[0].split(",")[0] + dboard_subdev_name = usrp_info.get("tx_subdev_name") dboard_serial = usrp_info.get("tx_serial") if dboard_serial == "": dboard_serial = "no serial" @@ -122,7 +122,7 @@ class top_block(gr.top_block, pubsub): antenna = self._u.get_antenna() desc_key_str = "Motherboard: %s [%s]\n" % (mboard_id, mboard_serial) - desc_key_str += "Daughterboard: %s [%s]\n" % (dboard_id, dboard_serial) + desc_key_str += "Daughterboard: %s [%s]\n" % (dboard_subdev_name, dboard_serial) desc_key_str += "Subdev: %s\n" % subdev desc_key_str += "Antenna: %s" % antenna except: diff --git a/gr-uhd/examples/grc/uhd_wbfm_receive.grc b/gr-uhd/examples/grc/uhd_wbfm_receive.grc index 62658a2eb..7f14123f2 100644 --- a/gr-uhd/examples/grc/uhd_wbfm_receive.grc +++ b/gr-uhd/examples/grc/uhd_wbfm_receive.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Sat Oct 8 15:18:49 2011</timestamp> + <timestamp>Tue Apr 24 16:59:09 2012</timestamp> <block> <key>options</key> <param> @@ -389,7 +389,15 @@ </param> <param> <key>type</key> - <value>complex</value> + <value>fc32</value> + </param> + <param> + <key>otw</key> + <value></value> + </param> + <param> + <key>stream_args</key> + <value></value> </param> <param> <key>dev_addr</key> @@ -408,7 +416,11 @@ <value>1</value> </param> <param> - <key>ref_source0</key> + <key>clock_source0</key> + <value></value> + </param> + <param> + <key>time_source0</key> <value></value> </param> <param> @@ -416,7 +428,11 @@ <value></value> </param> <param> - <key>ref_source1</key> + <key>clock_source1</key> + <value></value> + </param> + <param> + <key>time_source1</key> <value></value> </param> <param> @@ -424,7 +440,11 @@ <value></value> </param> <param> - <key>ref_source2</key> + <key>clock_source2</key> + <value></value> + </param> + <param> + <key>time_source2</key> <value></value> </param> <param> @@ -432,7 +452,11 @@ <value></value> </param> <param> - <key>ref_source3</key> + <key>clock_source3</key> + <value></value> + </param> + <param> + <key>time_source3</key> <value></value> </param> <param> @@ -440,7 +464,11 @@ <value></value> </param> <param> - <key>ref_source4</key> + <key>clock_source4</key> + <value></value> + </param> + <param> + <key>time_source4</key> <value></value> </param> <param> @@ -448,7 +476,11 @@ <value></value> </param> <param> - <key>ref_source5</key> + <key>clock_source5</key> + <value></value> + </param> + <param> + <key>time_source5</key> <value></value> </param> <param> @@ -456,7 +488,11 @@ <value></value> </param> <param> - <key>ref_source6</key> + <key>clock_source6</key> + <value></value> + </param> + <param> + <key>time_source6</key> <value></value> </param> <param> @@ -464,7 +500,11 @@ <value></value> </param> <param> - <key>ref_source7</key> + <key>clock_source7</key> + <value></value> + </param> + <param> + <key>time_source7</key> <value></value> </param> <param> @@ -1036,93 +1076,6 @@ </param> </block> <block> - <key>wxgui_fftsink2</key> - <param> - <key>id</key> - <value>wxgui_fftsink2</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>title</key> - <value>FFT Plot</value> - </param> - <param> - <key>samp_rate</key> - <value>samp_rate</value> - </param> - <param> - <key>baseband_freq</key> - <value>(freq+fine)*1e6</value> - </param> - <param> - <key>y_per_div</key> - <value>10</value> - </param> - <param> - <key>y_divs</key> - <value>10</value> - </param> - <param> - <key>ref_level</key> - <value>0</value> - </param> - <param> - <key>ref_scale</key> - <value>2.0</value> - </param> - <param> - <key>fft_size</key> - <value>512</value> - </param> - <param> - <key>fft_rate</key> - <value>15</value> - </param> - <param> - <key>peak_hold</key> - <value>False</value> - </param> - <param> - <key>average</key> - <value>False</value> - </param> - <param> - <key>avg_alpha</key> - <value>0</value> - </param> - <param> - <key>win</key> - <value>None</value> - </param> - <param> - <key>win_size</key> - <value></value> - </param> - <param> - <key>grid_pos</key> - <value>2, 0, 2, 4</value> - </param> - <param> - <key>notebook</key> - <value></value> - </param> - <param> - <key>_coordinate</key> - <value>(624, 278)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> <key>parameter</key> <param> <key>id</key> @@ -1332,6 +1285,93 @@ <value>0</value> </param> </block> + <block> + <key>wxgui_fftsink2</key> + <param> + <key>id</key> + <value>wxgui_fftsink2</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>title</key> + <value>FFT Plot</value> + </param> + <param> + <key>samp_rate</key> + <value>samp_rate</value> + </param> + <param> + <key>baseband_freq</key> + <value>(freq+fine)</value> + </param> + <param> + <key>y_per_div</key> + <value>10</value> + </param> + <param> + <key>y_divs</key> + <value>10</value> + </param> + <param> + <key>ref_level</key> + <value>0</value> + </param> + <param> + <key>ref_scale</key> + <value>2.0</value> + </param> + <param> + <key>fft_size</key> + <value>512</value> + </param> + <param> + <key>fft_rate</key> + <value>15</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0</value> + </param> + <param> + <key>win</key> + <value>None</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value>2, 0, 2, 4</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(624, 278)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> <connection> <source_block_id>gr_multiply_const_vxx</source_block_id> <sink_block_id>audio_sink</sink_block_id> diff --git a/gr-uhd/include/gr_uhd_usrp_sink.h b/gr-uhd/include/gr_uhd_usrp_sink.h index 0b05363f7..eaf60fb77 100644 --- a/gr-uhd/include/gr_uhd_usrp_sink.h +++ b/gr-uhd/include/gr_uhd_usrp_sink.h @@ -133,7 +133,7 @@ public: /*! * Returns identifying information about this USRP's configuration. * Returns motherboard ID, name, and serial. - * Returns daughterboard TX ID, subdev name, and serial. + * Returns daughterboard TX ID, subdev name and spec, serial, and antenna. * \param chan channel index 0 to N-1 * \return TX info */ diff --git a/gr-uhd/include/gr_uhd_usrp_source.h b/gr-uhd/include/gr_uhd_usrp_source.h index 2611c5e07..80d80bcb8 100644 --- a/gr-uhd/include/gr_uhd_usrp_source.h +++ b/gr-uhd/include/gr_uhd_usrp_source.h @@ -125,7 +125,7 @@ public: /*! * Returns identifying information about this USRP's configuration. * Returns motherboard ID, name, and serial. - * Returns daughterboard RX ID, subdev name, and serial. + * Returns daughterboard RX ID, subdev name and spec, serial, and antenna. * \param chan channel index 0 to N-1 * \return RX info */ diff --git a/grc/blocks/gr_file_sink.xml b/grc/blocks/gr_file_sink.xml index 0081c93f8..d0a693900 100644 --- a/grc/blocks/gr_file_sink.xml +++ b/grc/blocks/gr_file_sink.xml @@ -11,6 +11,7 @@ <make>gr.file_sink($type.size*$vlen, $file) self.$(id).set_unbuffered($unbuffered)</make> <callback>set_unbuffered($unbuffered)</callback> + <callback>open($file)</callback> <param> <name>File</name> <key>file</key> diff --git a/grc/blocks/gr_wavfile_sink.xml b/grc/blocks/gr_wavfile_sink.xml index f2c8a009f..651e16cb6 100644 --- a/grc/blocks/gr_wavfile_sink.xml +++ b/grc/blocks/gr_wavfile_sink.xml @@ -9,6 +9,7 @@ <key>gr_wavfile_sink</key> <import>from gnuradio import gr</import> <make>gr.wavfile_sink($file, $nchan, $samp_rate, $bits_per_sample)</make> + <callback>open($file)</callback> <param> <name>File</name> <key>file</key> diff --git a/gruel/src/include/gruel/pmt.h b/gruel/src/include/gruel/pmt.h index 92af1eba6..1e8b38627 100644 --- a/gruel/src/include/gruel/pmt.h +++ b/gruel/src/include/gruel/pmt.h @@ -32,7 +32,6 @@ #include <stdint.h> #include <iosfwd> #include <stdexcept> -#include <boost/function.hpp> namespace gruel { class msg_accepter; @@ -806,24 +805,6 @@ GRUEL_API std::string pmt_serialize_str(pmt_t obj); */ GRUEL_API pmt_t pmt_deserialize_str(std::string str); -/* - * ------------------------------------------------------------------------ - * advanced - * ------------------------------------------------------------------------ - */ - -#define GRUEL_PMT_HAVE_PMT_SET_DELETER - -/*! - * Set a deleter function to be called when the PMT dereferences. - * User beware! This function is for extremely advanced use. - * Use boost bind to bind extra parameters into the deleter function. - * Set an empty function type to reset the PMT to the default deleter. - * \param obj the pmt object in which to set the deleter function - * \param deleter a function that gets an opaque PMT pointer type - */ -GRUEL_API void pmt_set_deleter(pmt_t obj, boost::function<void(pmt_base *)> &deleter); - } /* namespace pmt */ #include <gruel/pmt_sugar.h> diff --git a/gruel/src/lib/pmt/CMakeLists.txt b/gruel/src/lib/pmt/CMakeLists.txt index dc70f03d7..72bd27a04 100644 --- a/gruel/src/lib/pmt/CMakeLists.txt +++ b/gruel/src/lib/pmt/CMakeLists.txt @@ -67,7 +67,7 @@ add_custom_command( ${CMAKE_CURRENT_SOURCE_DIR}/unv_template.h.t ${CMAKE_CURRENT_SOURCE_DIR}/unv_template.cc.t ${CMAKE_CURRENT_SOURCE_DIR}/unv_qa_template.cc.t - COMMAND ${PYTHON_EXECUTABLE} -B -c + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} -c \"import os,sys\;srcdir='${CMAKE_CURRENT_SOURCE_DIR}'\;sys.path.append(srcdir)\;os.environ['srcdir']=srcdir\;from generate_unv import main\;main()\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) diff --git a/gruel/src/lib/pmt/pmt.cc b/gruel/src/lib/pmt/pmt.cc index a7e0fd19f..1d9125d4e 100644 --- a/gruel/src/lib/pmt/pmt.cc +++ b/gruel/src/lib/pmt/pmt.cc @@ -58,7 +58,7 @@ pmt_base::operator delete(void *p, size_t size) #endif void intrusive_ptr_add_ref(pmt_base* p) { ++(p->count_); } -void intrusive_ptr_release(pmt_base* p) { if (--(p->count_) == 0 ) p->deleter_(p); } +void intrusive_ptr_release(pmt_base* p) { if (--(p->count_) == 0 ) delete p; } pmt_base::~pmt_base() { @@ -1383,16 +1383,4 @@ pmt_dump_sizeof() printf("sizeof(pmt_uniform_vector) = %3zd\n", sizeof(pmt_uniform_vector)); } -/* - * ------------------------------------------------------------------------ - * advanced - * ------------------------------------------------------------------------ - */ - -void -pmt_set_deleter(pmt_t obj, boost::function<void(pmt_base *)> &deleter) -{ - obj->deleter_ = (deleter)? deleter : &pmt_base::default_deleter; -} - } /* namespace pmt */ diff --git a/gruel/src/lib/pmt/pmt_int.h b/gruel/src/lib/pmt/pmt_int.h index bd2b5fe5a..d669e1049 100644 --- a/gruel/src/lib/pmt/pmt_int.h +++ b/gruel/src/lib/pmt/pmt_int.h @@ -38,15 +38,8 @@ namespace pmt { class GRUEL_API pmt_base : boost::noncopyable { mutable boost::detail::atomic_count count_; -public: - static void default_deleter(pmt_base *p){ - delete p; - } - - boost::function<void(pmt_base *)> deleter_; - protected: - pmt_base() : count_(0), deleter_(&pmt::pmt_base::default_deleter) {}; + pmt_base() : count_(0) {}; virtual ~pmt_base(); public: diff --git a/volk/CMakeLists.txt b/volk/CMakeLists.txt index fdde308ad..68385f974 100644 --- a/volk/CMakeLists.txt +++ b/volk/CMakeLists.txt @@ -54,10 +54,30 @@ SET(CROSSCOMPILE_MULTILIB ${CROSSCOMPILE_MULTILIB} CACHE STRING "Define \"true\" ######################################################################## # Dependencies setup ######################################################################## -find_package(PythonInterp REQUIRED PYTHON_EXECUTABLE) +include(GrPython) #sets PYTHON_EXECUTABLE and PYTHON_DASH_B +GR_PYTHON_CHECK_MODULE("python >= 2.5" sys "sys.version.split()[0] >= '2.5'" PYTHON_MIN_VER_FOUND) +GR_PYTHON_CHECK_MODULE("Cheetah >= 2.0.0" Cheetah "Cheetah.Version >= '2.0.0'" CHEETAH_FOUND) + +if(NOT PYTHON_MIN_VER_FOUND) + message(FATAL_ERROR "Python 2.5 or greater required to build VOLK") +endif() + +if(NOT CHEETAH_FOUND) + message(FATAL_ERROR "Cheetah templates required to build VOLK") +endif() + +set(Boost_ADDITIONAL_VERSIONS + "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" + "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" + "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" + "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" + "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" + "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" + "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" +) find_package(Boost COMPONENTS unit_test_framework) -find_package(ORC) +find_package(ORC) ######################################################################## # Setup the package config file diff --git a/volk/apps/CMakeLists.txt b/volk/apps/CMakeLists.txt index 14291e5e3..175105a5a 100644 --- a/volk/apps/CMakeLists.txt +++ b/volk/apps/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011-2012 Free Software Foundation, Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -43,9 +43,8 @@ add_executable(volk_profile target_link_libraries(volk_profile volk ${Boost_LIBRARIES}) install( - PROGRAMS - ${CMAKE_BINARY_DIR}/apps/volk_profile - DESTINATION ${GR_RUNTIME_DIR} + TARGETS volk_profile + DESTINATION bin COMPONENT "volk" ) diff --git a/volk/cmake/GrPython.cmake b/volk/cmake/GrPython.cmake new file mode 100644 index 000000000..eff9cbcdc --- /dev/null +++ b/volk/cmake/GrPython.cmake @@ -0,0 +1,233 @@ +# Copyright 2010-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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +if(DEFINED __INCLUDED_GR_PYTHON_CMAKE) + return() +endif() +set(__INCLUDED_GR_PYTHON_CMAKE TRUE) + +######################################################################## +# Setup the python interpreter: +# This allows the user to specify a specific interpreter, +# or finds the interpreter via the built-in cmake module. +######################################################################## +#this allows the user to override PYTHON_EXECUTABLE +if(PYTHON_EXECUTABLE) + + set(PYTHONINTERP_FOUND TRUE) + +#otherwise if not set, try to automatically find it +else(PYTHON_EXECUTABLE) + + #use the built-in find script + find_package(PythonInterp) + + #and if that fails use the find program routine + if(NOT PYTHONINTERP_FOUND) + find_program(PYTHON_EXECUTABLE NAMES python python2.7 python2.6 python2.5) + if(PYTHON_EXECUTABLE) + set(PYTHONINTERP_FOUND TRUE) + endif(PYTHON_EXECUTABLE) + endif(NOT PYTHONINTERP_FOUND) + +endif(PYTHON_EXECUTABLE) + +#make the path to the executable appear in the cmake gui +set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") + +#make sure we can use -B with python (introduced in 2.6) +if(PYTHON_EXECUTABLE) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -B -c "" + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT + ) + if(PYTHON_HAS_DASH_B_RESULT EQUAL 0) + set(PYTHON_DASH_B "-B") + endif() +endif(PYTHON_EXECUTABLE) + +######################################################################## +# Check for the existence of a python module: +# - desc a string description of the check +# - mod the name of the module to import +# - cmd an additional command to run +# - have the result variable to set +######################################################################## +macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) + message(STATUS "") + message(STATUS "Python checking for ${desc}") + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c " +######################################### +try: import ${mod} +except: + try: ${mod} + except: exit(-1) +try: assert ${cmd} +except: exit(-1) +#########################################" + RESULT_VARIABLE ${have} + ) + if(${have} EQUAL 0) + message(STATUS "Python checking for ${desc} - found") + set(${have} TRUE) + else(${have} EQUAL 0) + message(STATUS "Python checking for ${desc} - not found") + set(${have} FALSE) + endif(${have} EQUAL 0) +endmacro(GR_PYTHON_CHECK_MODULE) + +######################################################################## +# Sets the python installation directory GR_PYTHON_DIR +######################################################################## +execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " +from distutils import sysconfig +print sysconfig.get_python_lib(plat_specific=True, prefix='') +" OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE +) +file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) + +######################################################################## +# Create an always-built target with a unique name +# Usage: GR_UNIQUE_TARGET(<description> <dependencies list>) +######################################################################## +function(GR_UNIQUE_TARGET desc) + file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib +unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] +print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" + OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) + add_custom_target(${_target} ALL DEPENDS ${ARGN}) +endfunction(GR_UNIQUE_TARGET) + +######################################################################## +# Install python sources (also builds and installs byte-compiled python) +######################################################################## +function(GR_PYTHON_INSTALL) + include(CMakeParseArgumentsCopy) + CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN}) + + #################################################################### + if(GR_PYTHON_INSTALL_FILES) + #################################################################### + install(${ARGN}) #installs regular python files + + #create a list of all generated files + unset(pysrcfiles) + unset(pycfiles) + unset(pyofiles) + foreach(pyfile ${GR_PYTHON_INSTALL_FILES}) + get_filename_component(pyfile ${pyfile} ABSOLUTE) + list(APPEND pysrcfiles ${pyfile}) + + #determine if this file is in the source or binary directory + file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile}) + string(LENGTH "${source_rel_path}" source_rel_path_len) + file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile}) + string(LENGTH "${binary_rel_path}" binary_rel_path_len) + + #and set the generated path appropriately + if(${source_rel_path_len} GREATER ${binary_rel_path_len}) + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path}) + else() + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path}) + endif() + list(APPEND pycfiles ${pygenfile}c) + list(APPEND pyofiles ${pygenfile}o) + + #ensure generation path exists + get_filename_component(pygen_path ${pygenfile} PATH) + file(MAKE_DIRECTORY ${pygen_path}) + + endforeach(pyfile) + + #the command to generate the pyc files + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pycfiles} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles} + ) + + #the command to generate the pyo files + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pyofiles} + COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles} + ) + + #create install rule and add generated files to target list + set(python_install_gen_targets ${pycfiles} ${pyofiles}) + install(FILES ${python_install_gen_targets} + DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} + COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} + ) + + + #################################################################### + elseif(GR_PYTHON_INSTALL_PROGRAMS) + #################################################################### + file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) + + if (CMAKE_CROSSCOMPILING) + set(pyexe_native /usr/bin/env python) + endif() + + foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS}) + get_filename_component(pyfile_name ${pyfile} NAME) + get_filename_component(pyfile ${pyfile} ABSOLUTE) + string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe") + list(APPEND python_install_gen_targets ${pyexefile}) + + get_filename_component(pyexefile_path ${pyexefile} PATH) + file(MAKE_DIRECTORY ${pyexefile_path}) + + add_custom_command( + OUTPUT ${pyexefile} DEPENDS ${pyfile} + COMMAND ${PYTHON_EXECUTABLE} -c + \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\" + COMMENT "Shebangin ${pyfile_name}" + ) + + #on windows, python files need an extension to execute + get_filename_component(pyfile_ext ${pyfile} EXT) + if(WIN32 AND NOT pyfile_ext) + set(pyfile_name "${pyfile_name}.py") + endif() + + install(PROGRAMS ${pyexefile} RENAME ${pyfile_name} + DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} + COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} + ) + endforeach(pyfile) + + endif() + + GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets}) + +endfunction(GR_PYTHON_INSTALL) + +######################################################################## +# Write the python helper script that generates byte code files +######################################################################## +file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " +import sys, py_compile +files = sys.argv[1:] +srcs, gens = files[:len(files)/2], files[len(files)/2:] +for src, gen in zip(srcs, gens): + py_compile.compile(file=src, cfile=gen, doraise=True) +") diff --git a/volk/cmake/msvc/config.h b/volk/cmake/msvc/config.h new file mode 100644 index 000000000..43792c783 --- /dev/null +++ b/volk/cmake/msvc/config.h @@ -0,0 +1,58 @@ +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_CONFIG_H_ // [ +#define _MSC_CONFIG_H_ + +//////////////////////////////////////////////////////////////////////// +// enable inline functions for C code +//////////////////////////////////////////////////////////////////////// +#ifndef __cplusplus +# define inline __inline +#endif + +//////////////////////////////////////////////////////////////////////// +// signed size_t +//////////////////////////////////////////////////////////////////////// +#include <stddef.h> +typedef ptrdiff_t ssize_t; + +//////////////////////////////////////////////////////////////////////// +// rint functions +//////////////////////////////////////////////////////////////////////// +#include <math.h> +static inline long lrint(double x){return (long)(x > 0.0 ? x + 0.5 : x - 0.5);} +static inline long lrintf(float x){return (long)(x > 0.0f ? x + 0.5f : x - 0.5f);} +static inline long long llrint(double x){return (long long)(x > 0.0 ? x + 0.5 : x - 0.5);} +static inline long long llrintf(float x){return (long long)(x > 0.0f ? x + 0.5f : x - 0.5f);} +static inline double rint(double x){return (x > 0.0)? floor(x + 0.5) : ceil(x - 0.5);} +static inline float rintf(float x){return (x > 0.0f)? floorf(x + 0.5f) : ceilf(x - 0.5f);} + +//////////////////////////////////////////////////////////////////////// +// math constants +//////////////////////////////////////////////////////////////////////// +#define INFINITY HUGE_VAL + +# define M_E 2.7182818284590452354 /* e */ +# define M_LOG2E 1.4426950408889634074 /* log_2 e */ +# define M_LOG10E 0.43429448190325182765 /* log_10 e */ +# define M_LN2 0.69314718055994530942 /* log_e 2 */ +# define M_LN10 2.30258509299404568402 /* log_e 10 */ +# define M_PI 3.14159265358979323846 /* pi */ +# define M_PI_2 1.57079632679489661923 /* pi/2 */ +# define M_PI_4 0.78539816339744830962 /* pi/4 */ +# define M_1_PI 0.31830988618379067154 /* 1/pi */ +# define M_2_PI 0.63661977236758134308 /* 2/pi */ +# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ + +//////////////////////////////////////////////////////////////////////// +// random and srandom +//////////////////////////////////////////////////////////////////////// +#include <stdlib.h> +static inline long int random (void) { return rand(); } +static inline void srandom (unsigned int seed) { srand(seed); } + +#endif // _MSC_CONFIG_H_ ] diff --git a/volk/msvc/inttypes.h b/volk/cmake/msvc/inttypes.h index 0a1b60fc1..0a1b60fc1 100644 --- a/volk/msvc/inttypes.h +++ b/volk/cmake/msvc/inttypes.h diff --git a/volk/msvc/stdint.h b/volk/cmake/msvc/stdint.h index 108bc8982..108bc8982 100644 --- a/volk/msvc/stdint.h +++ b/volk/cmake/msvc/stdint.h diff --git a/volk/gen/archs.xml b/volk/gen/archs.xml index ca2118475..2c9ab41a5 100644 --- a/volk/gen/archs.xml +++ b/volk/gen/archs.xml @@ -1,153 +1,183 @@ <!-- archs appear in order of significance for blind, de-facto version ordering --> <grammar> -<arch name="generic" type="all"> <!-- name and type are both required--> - <flag>none</flag> <!-- flag is the only required field--> +<arch name="generic"> <!-- name is required--> </arch> -<arch name="altivec" type="powerpc"> - <flag>maltivec</flag> +<arch name="altivec"> + <flag compiler="gnu">-maltivec</flag> <alignment>16</alignment> + <check name="has_ppc"></check> </arch> -<arch name="neon" type="arm"> - <flag>mfpu=neon,mfloat-abi=softfp,funsafe-math-optimizations</flag> +<arch name="neon"> + <flag compiler="gnu">-mfpu=neon</flag> + <flag compiler="gnu">-mfloat-abi=softfp</flag> + <flag compiler="gnu">-funsafe-math-optimizations</flag> <alignment>16</alignment> + <check name="has_neon"></check> </arch> -<arch name="32" type="x86" no_test="true" > - <flag>m32</flag> - <overrule>MD_SUBCPU</overrule> - <overrule_val>x86_64</overrule_val> +<arch name="32"> + <flag compiler="gnu">-m32</flag> </arch> -<arch name="64" type="x86"> - <op>0x80000001</op> - <reg>d</reg> - <shift>29</shift> - <flag>m64</flag> - <val>1</val> - <overrule>MD_SUBCPU</overrule> - <overrule_val>x86</overrule_val> +<arch name="64"> + <check name="check_extended_cpuid"> + <param>0x80000001</param> + </check> + <check name="cpuid_x86_bit"> <!-- checks to see if a bit is set --> + <param>3</param> <!-- eax, ebx, ecx, [edx] --> + <param>0x80000001</param> <!-- cpuid operation --> + <param>29</param> <!-- bit shift --> + </check> + <flag compiler="gnu">-m64</flag> </arch> -<arch name="3dnow" type="x86"> - <op>0x80000001</op> - <reg>d</reg> - <shift>31</shift> - <flag>m3dnow</flag> - <val>1</val> +<arch name="3dnow"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x80000001</param> + <param>31</param> + </check> + <flag compiler="gnu">-m3dnow</flag> <alignment>8</alignment> </arch> -<arch name="abm" type="x86"> - <val>1</val> - <op>0x80000001</op> - <reg>d</reg> - <shift>5</shift> - <flag>msse4.2</flag> +<arch name="abm"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x80000001</param> + <param>5</param> + </check> + <flag compiler="gnu">-msse4.2</flag> <alignment>16</alignment> </arch> -<arch name="popcount" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>23</shift> - <flag>mpopcnt</flag> -</arch> - -<arch name="mmx" type="x86"> - <val>1</val> - <op>1</op> - <reg>d</reg> - <shift>23</shift> - <flag>mmmx</flag> +<arch name="popcount"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>23</param> + </check> + <flag compiler="gnu">-mpopcnt</flag> + <flag compiler="msvc">/arch:AVX</flag> +</arch> + +<arch name="mmx"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x00000001</param> + <param>23</param> + </check> + <flag compiler="gnu">-mmmx</flag> + <flag compiler="msvc">/arch:SSE</flag> <alignment>8</alignment> </arch> - -<arch name="sse" type="x86"> - <val>1</val> - <op>1</op> - <reg>d</reg> - <shift>25</shift> - <flag>msse</flag> +<arch name="sse"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x00000001</param> + <param>25</param> + </check> + <flag compiler="gnu">-msse</flag> + <flag compiler="msvc">/arch:SSE</flag> <environment>_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);</environment> <include>xmmintrin.h</include> <alignment>16</alignment> </arch> - -<arch name="sse2" type="x86"> - <val>1</val> - <op>1</op> - <reg>d</reg> - <shift>26</shift> - <flag>msse2</flag> +<arch name="sse2"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x00000001</param> + <param>26</param> + </check> + <flag compiler="gnu">-msse2</flag> + <flag compiler="msvc">/arch:SSE2</flag> <alignment>16</alignment> </arch> -<arch name="orc" type="all"> - <flag>lorc-0.4</flag> - <overrule>LV_HAVE_ORC</overrule> - <overrule_val>no</overrule_val> +<arch name="orc"> </arch> -<arch name="sse3" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>0</shift> - <flag>msse3</flag> +<!-- it's here for overrule stuff. --> +<arch name="norc"> +</arch> + +<arch name="sse3"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>0</param> + </check> + <flag compiler="gnu">-msse3</flag> + <flag compiler="msvc">/arch:AVX</flag> <environment>_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);</environment> <include>pmmintrin.h</include> <alignment>16</alignment> </arch> -<arch name="ssse3" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>9</shift> - <flag>mssse3</flag> +<arch name="ssse3"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>9</param> + </check> + <flag compiler="gnu">-mssse3</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>16</alignment> </arch> -<arch name="sse4_a" type="x86"> - <val>1</val> - <op>0x80000001</op> - <reg>c</reg> - <shift>6</shift> - <flag>msse4a</flag> +<arch name="sse4_a"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x80000001</param> + <param>6</param> + </check> + <flag compiler="gnu">-msse4a</flag> <alignment>16</alignment> </arch> - -<arch name="sse4_1" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>19</shift> - <flag>msse4.1</flag> +<arch name="sse4_1"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>19</param> + </check> + <flag compiler="gnu">-msse4.1</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>16</alignment> </arch> -<arch name="sse4_2" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>20</shift> - <flag>msse4.2</flag> +<arch name="sse4_2"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>20</param> + </check> + <flag compiler="gnu">-msse4.2</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>16</alignment> </arch> -<arch name="avx" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>28</shift> - <flag>mavx</flag> +<arch name="avx"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>28</param> + </check> + <!-- check to make sure that xgetbv is enabled in OS --> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>27</param> + </check> + <!-- check to see that the OS has enabled AVX --> + <check name="get_avx_enabled"></check> + <flag compiler="gnu">-mavx</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>32</alignment> </arch> diff --git a/volk/gen/compilers.xml b/volk/gen/compilers.xml deleted file mode 100644 index 005eda2aa..000000000 --- a/volk/gen/compilers.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- compilers remap gcc-specific information from archs.xml to specific compiler cases--> -<grammar> - -<compiler name="MSVC"> - <!-- remap the following flags to SSE --> - <remap name="mmmx">arch:SSE</remap> - <remap name="msse">arch:SSE</remap> - - <!-- remap the following flags to SSE2 --> - <remap name="msse2">arch:SSE2</remap> - - <!-- remap the following flags to AVX --> - <remap name="msse3">arch:AVX</remap> - <remap name="mssse3">arch:AVX</remap> - <remap name="msse4.1">arch:AVX</remap> - <remap name="msse4.2">arch:AVX</remap> - <remap name="mpopcnt">arch:AVX</remap> - <remap name="mavx">arch:AVX</remap> - - <prefix>/</prefix> -</compiler> - -<compiler name="GNU"> - <prefix>-</prefix> -</compiler> - - - - -</grammar> diff --git a/volk/gen/machines.xml b/volk/gen/machines.xml index 9c19c91c6..8e3c9c8c2 100644 --- a/volk/gen/machines.xml +++ b/volk/gen/machines.xml @@ -1,64 +1,51 @@ <grammar> <machine name="generic"> -<archs>generic</archs> +<archs>generic orc|</archs> </machine> <!-- <machine name="mmx"> -<archs>generic 32|64 mmx</archs> +<archs>generic 32|64 mmx orc|</archs> </machine> <machine name="sse"> -<archs>generic 32|64 mmx sse</archs> +<archs>generic 32|64| mmx sse orc|</archs> </machine> --> -<!-- -Create an SSE2 and AVX only machine (without 64/32 inline assembly support). -This machine is intended to support the MSVC compiler on x86/amd64. -The MSVC compiler has intrinsic support for SSE, SSE2, AVX -however it does not support the gcc style inline assembly. ---> - <machine name="neon"> -<archs>generic neon</archs> -</machine> - -<machine name="sse2_only"> -<archs>generic mmx sse sse2</archs> +<archs>generic neon orc|</archs> </machine> +<!-- trailing | bar means generate without either for MSVC --> <machine name="sse2"> -<archs>generic 32|64 mmx sse sse2</archs> +<archs>generic 32|64| mmx sse sse2 orc|</archs> </machine> <machine name="sse3"> -<archs>generic 32|64 mmx sse sse2 sse3</archs> +<archs>generic 32|64 mmx sse sse2 sse3 orc|</archs> </machine> <machine name="ssse3"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3</archs> +<archs>generic 32|64 mmx sse sse2 sse3 ssse3 orc|</archs> </machine> <machine name="sse4_a"> -<archs>generic 32|64 mmx sse sse2 sse3 sse4_a popcount</archs> +<archs>generic 32|64 mmx sse sse2 sse3 sse4_a popcount orc|</archs> </machine> <machine name="sse4_1"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1</archs> +<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 orc|</archs> </machine> <machine name="sse4_2"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount</archs> +<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount orc|</archs> </machine> +<!-- trailing | bar means generate without either for MSVC --> <machine name="avx"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx</archs> -</machine> - -<machine name="avx_only"> -<archs>generic mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx</archs> +<archs>generic 32|64| mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx orc|</archs> </machine> <machine name="altivec"> diff --git a/volk/gen/make_c.py b/volk/gen/make_c.py deleted file mode 100644 index 233cb85c2..000000000 --- a/volk/gen/make_c.py +++ /dev/null @@ -1,88 +0,0 @@ -# -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program 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, see <http://www.gnu.org/licenses/>. -# - -from volk_regexp import * -import string - -#ok todo list: -#put n_archs into the info struct so it doesn't have to be arch_defs[0]. - -def make_c(machines, archs, functions, arched_arglist, my_arglist): - tempstring = r""" -// This file is automatically generated by make_c.py. -// Do not edit this file. -""" - tempstring += """ -#include <volk/volk_common.h> -#include "volk_machines.h" -#include <volk/volk_typedefs.h> -#include <volk/volk_cpu.h> -#include "volk_rank_archs.h" -#include <volk/volk.h> -#include <stdio.h> -#include <string.h> - -""" - -#OK here's the deal. the .h prototypes the functions. the .c impls them as fptrs, can use p_whatever. -#also .c impls the get_machine call -#also .c impls the default call for each fn - -#here do static fn get arch - tempstring += r""" -struct volk_machine *get_machine(void) { - extern struct volk_machine *volk_machines[]; - extern unsigned int n_volk_machines; - static struct volk_machine *machine = NULL; - - if(machine != NULL) return machine; - else { - unsigned int max_score = 0; - unsigned int i; - for(i=0; i<n_volk_machines; i++) { - if(!(volk_machines[i]->caps & (~volk_get_lvarch()))) { - if(volk_machines[i]->caps > max_score) { - max_score = volk_machines[i]->caps; - machine = volk_machines[i]; - } - } - } - printf("Using Volk machine: %s\n", machine->name); - return machine; - } -} - -unsigned int volk_get_alignment(void) { - return get_machine()->alignment; -} - -""" - - for i in range(len(functions)): - tempstring += "void get_" + functions[i] + replace_arch.sub("", arched_arglist[i]) + "\n" - tempstring += " %s = get_machine()->%s_archs[volk_rank_archs(get_machine()->%s_indices, get_machine()->%s_arch_defs, get_machine()->%s_n_archs, get_machine()->%s_name, volk_get_lvarch())];\n" % (functions[i], functions[i], functions[i], functions[i], functions[i], functions[i]) - tempstring += " %s(%s);\n}\n\n" % (functions[i], my_arglist[i]) - tempstring += replace_volk.sub("p", functions[i]) + " " + functions[i] + " = &get_" + functions[i] + ";\n\n" - tempstring += "void %s_manual%s\n" % (functions[i], arched_arglist[i]) - tempstring += " get_machine()->%s_archs[get_index(get_machine()->%s_indices, get_machine()->%s_n_archs, arch)](%s);\n}\n" % (functions[i], functions[i], functions[i], my_arglist[i]) - tempstring += "struct volk_func_desc %s_get_func_desc(void) {\n" % (functions[i]) - tempstring += " struct volk_func_desc desc = {get_machine()->%s_indices, get_machine()->%s_arch_defs, get_machine()->%s_n_archs};\n" % (functions[i], functions[i], functions[i]) - tempstring += " return desc;\n}\n" - - return tempstring - - diff --git a/volk/gen/make_config_fixed.py b/volk/gen/make_config_fixed.py deleted file mode 100644 index 96f20b6b2..000000000 --- a/volk/gen/make_config_fixed.py +++ /dev/null @@ -1,21 +0,0 @@ -from xml.dom import minidom - -def make_config_fixed(dom) : - tempstring = ""; - tempstring = tempstring +'/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '\n#ifndef INCLUDED_VOLK_CONFIG_FIXED_H'; - tempstring = tempstring + '\n#define INCLUDED_VOLK_CONFIG_FIXED_H'; - tempstring = tempstring + '\n\n'; - enum_counter = 0; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + '#define LV_' + arch.swapcase() + " " + str(enum_counter) + '\n'; - enum_counter = enum_counter + 1; - tempstring = tempstring + '\n\n'; - - tempstring = tempstring + "#endif /*INCLUDED_VOLK_CONFIG_FIXED*/\n" - - return tempstring; - - - diff --git a/volk/gen/make_config_in.py b/volk/gen/make_config_in.py deleted file mode 100644 index d29680af2..000000000 --- a/volk/gen/make_config_in.py +++ /dev/null @@ -1,13 +0,0 @@ -from xml.dom import minidom - -def make_config_in(dom) : - tempstring = ""; - tempstring = tempstring +'/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '\n\n'; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + '#undef LV_HAVE_' + arch.swapcase() + '\n'; - tempstring = tempstring + '\n'; - - return tempstring diff --git a/volk/gen/make_cpuid_c.py b/volk/gen/make_cpuid_c.py deleted file mode 100644 index e30d643cb..000000000 --- a/volk/gen/make_cpuid_c.py +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from xml.dom import minidom - -HEADER_TEMPL = """\ -/*this file is auto_generated by volk_register.py*/ - -#include <volk/volk_cpu.h> -#include <volk/volk_config_fixed.h> - -struct VOLK_CPU volk_cpu; - -#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) -# define VOLK_CPU_x86 -#endif - -#if defined(VOLK_CPU_x86) - -//implement get cpuid for gcc compilers using a copy of cpuid.h -#if defined(__GNUC__) -#include <gcc_x86_cpuid.h> -#define cpuid_x86(op, r) __get_cpuid(op, (unsigned int *)r+0, (unsigned int *)r+1, (unsigned int *)r+2, (unsigned int *)r+3) - -//implement get cpuid for MSVC compilers using __cpuid intrinsic -#elif defined(_MSC_VER) -#include <intrin.h> -#define cpuid_x86(op, r) __cpuid(r, op) - -#else -#error "A get cpuid for volk is not available on this compiler..." -#endif - -static inline unsigned int cpuid_eax(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[0]; -} - -static inline unsigned int cpuid_ebx(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[1]; -} - -static inline unsigned int cpuid_ecx(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[2]; -} - -static inline unsigned int cpuid_edx(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[3]; -} -#endif - -""" - -def make_cpuid_c(dom) : - tempstring = HEADER_TEMPL; - - for domarch in dom: - if str(domarch.attributes["type"].value) == "x86": - if "no_test" in domarch.attributes.keys(): - no_test = str(domarch.attributes["no_test"].value); - if no_test == "true": - no_test = True; - else: - no_test = False; - else: - no_test = False; - arch = str(domarch.attributes["name"].value); - op = domarch.getElementsByTagName("op"); - if op: - op = str(op[0].firstChild.data); - reg = domarch.getElementsByTagName("reg"); - if reg: - reg = str(reg[0].firstChild.data); - shift = domarch.getElementsByTagName("shift"); - if shift: - shift = str(shift[0].firstChild.data); - val = domarch.getElementsByTagName("val"); - if val: - val = str(val[0].firstChild.data); - - if no_test: - tempstring = tempstring + """\ -int i_can_has_%s () { -#if defined(VOLK_CPU_x86) - return 1; -#else - return 0; -#endif -} - -""" % (arch) - - elif op == "1": - tempstring = tempstring + """\ -int i_can_has_%s () { -#if defined(VOLK_CPU_x86) - unsigned int e%sx = cpuid_e%sx (%s); - return ((e%sx >> %s) & 1) == %s; -#else - return 0; -#endif -} - -""" % (arch, reg, reg, op, reg, shift, val) - - elif op == "0x80000001": - tempstring = tempstring + """\ -int i_can_has_%s () { -#if defined(VOLK_CPU_x86) - unsigned int extended_fct_count = cpuid_eax(0x80000000); - if (extended_fct_count < 0x80000001) - return %s^1; - unsigned int extended_features = cpuid_e%sx (%s); - return ((extended_features >> %s) & 1) == %s; -#else - return 0; -#endif -} - -""" % (arch, val, reg, op, shift, val) - - elif str(domarch.attributes["type"].value) == "powerpc": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -int i_can_has_%s () { -#ifdef __PPC__ - return 1; -#else - return 0; -#endif -} - -""" % (arch) - - elif str(domarch.attributes["type"].value) == "arm": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -#if defined(__arm__) && defined(__linux__) -#include <asm/hwcap.h> -#include <linux/auxvec.h> -#include <stdio.h> -#define LOOK_FOR_NEON -#endif - -int i_can_has_%s () { -//it's linux-specific, but if you're compiling libvolk for NEON -//on Windows you have other problems - -#ifdef LOOK_FOR_NEON - FILE *auxvec_f; - unsigned long auxvec[2]; - unsigned int found_neon = 0; - auxvec_f = fopen("/proc/self/auxv", "rb"); - if(!auxvec_f) return 0; - - //so auxv is basically 32b of ID and 32b of value - //so it goes like this - while(!found_neon && auxvec_f) { - fread(auxvec, sizeof(unsigned long), 2, auxvec_f); - if((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_NEON)) - found_neon = 1; - } - - fclose(auxvec_f); - return found_neon; - -#else - return 0; -#endif -} - -""" % (arch) - - elif str(domarch.attributes["type"].value) == "all": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -int i_can_has_%s () { - return 1; -} - -""" % (arch) - else: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -int i_can_has_%s () { - return 0; -} - -""" % (arch) - - tempstring = tempstring + "void volk_cpu_init() {\n"; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " volk_cpu.has_" + arch + " = &i_can_has_" + arch + ";\n" - tempstring = tempstring + "}\n\n" - - tempstring = tempstring + "unsigned int volk_get_lvarch() {\n"; - tempstring = tempstring + " unsigned int retval = 0;\n" - tempstring = tempstring + " volk_cpu_init();\n" - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " retval += volk_cpu.has_" + arch + "() << LV_" + arch.swapcase() + ";\n" - tempstring = tempstring + " return retval;\n" - tempstring = tempstring + "}\n\n" - - return tempstring; - - - - - - - diff --git a/volk/gen/make_cpuid_h.py b/volk/gen/make_cpuid_h.py deleted file mode 100644 index 1aa783781..000000000 --- a/volk/gen/make_cpuid_h.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from xml.dom import minidom - -def make_cpuid_h(dom) : - tempstring = ""; - tempstring = tempstring +'/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring +'\n#ifndef INCLUDED_VOLK_CPU_H'; - tempstring = tempstring +'\n#define INCLUDED_VOLK_CPU_H\n\n'; - tempstring = tempstring + "#include <volk/volk_common.h>\n\n"; - tempstring = tempstring + '__VOLK_DECL_BEGIN\n'; - tempstring = tempstring + '\n' - - tempstring = tempstring + "struct VOLK_CPU {\n" - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " int (*has_" + arch + ") ();\n"; - tempstring = tempstring + "};\n\n"; - tempstring = tempstring + "extern struct VOLK_CPU volk_cpu;\n\n"; - - tempstring = tempstring + "void volk_cpu_init ();\n" - tempstring = tempstring + "unsigned int volk_get_lvarch ();\n" - - tempstring = tempstring + "\n"; - tempstring = tempstring + "__VOLK_DECL_END\n"; - tempstring = tempstring + "#endif /*INCLUDED_VOLK_CPU_H*/\n" - - return tempstring; diff --git a/volk/gen/make_each_machine_c.py b/volk/gen/make_each_machine_c.py deleted file mode 100644 index 535578859..000000000 --- a/volk/gen/make_each_machine_c.py +++ /dev/null @@ -1,90 +0,0 @@ -# -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program 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, see <http://www.gnu.org/licenses/>. -# - -from volk_regexp import * -import string - -def _make_each_machine_struct(machine_name, archs, functions, fcountlist, taglist, alignment): - - #make the machine fcountlist and taglist a subset given the archs list - machine_fcountlists = list() - machine_taglists = list() - for i in range(len(fcountlist)): - machine_fcountlist = list() - machine_taglist = list() - for j in range(len(fcountlist[i])): - if len(set(archs).intersection(map(str.lower, fcountlist[i][j]))) == len(fcountlist[i][j]): - machine_fcountlist.append(fcountlist[i][j]) - machine_taglist.append(taglist[i][j]) - machine_fcountlists.append(machine_fcountlist) - machine_taglists.append(machine_taglist) - - #create the volk machine struct for this machine file - tempstring = "" - tempstring += "struct volk_machine volk_machine_" + machine_name + " = {\n" - tempstring += " " + ' | '.join(["(1 << LV_" + arch.swapcase() + ")" for arch in archs]) + ",\n" - tempstring += " \"%s\",\n"%machine_name - tempstring += " %s,\n"%alignment - - #fill in the description for each function - for i in range(len(functions)): - tempstring += " \"%s\",\n"%functions[i] - tempstring += " {%s},\n"%(', '.join(['"%s"'%tag for tag in machine_taglists[i]])) - tempstring += " {%s},\n"%(', '.join([' | '.join(['(1 << LV_%s)'%fc for fc in fcount]) for fcount in machine_fcountlists[i]])) - tempstring += " {%s},\n"%(', '.join(['%s_%s'%(functions[i], tag) for tag in machine_taglists[i]])) - tempstring += " %d,\n"%len(machine_taglists[i]) - - tempstring = strip_trailing(tempstring, ",") - tempstring += "};\n" - return tempstring - -def make_each_machine_c(machine_name, archs, functions, fcountlist, taglist, alignment): - tempstring = r""" -// This file is automatically generated by make_each_machine_c.py. -// Do not edit this file. -""" - for arch in archs: - tempstring += "#define LV_HAVE_" + arch.swapcase() + " 1\n" - - tempstring += """ -#include <volk/volk_common.h> -#include "volk_machines.h" -#include <volk/volk_config_fixed.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -""" - for func in functions: - tempstring += "#include <volk/" + func + ".h>\n" - tempstring += "\n\n" - - tempstring += """ -#ifdef LV_HAVE_ORC -%s -#else -%s -#endif -"""%( - _make_each_machine_struct(machine_name, archs+["orc"], functions, fcountlist, taglist, alignment), - _make_each_machine_struct(machine_name, archs, functions, fcountlist, taglist, alignment) -) - - return tempstring - - diff --git a/volk/gen/make_environment_init_c.py b/volk/gen/make_environment_init_c.py deleted file mode 100644 index 6186162ee..000000000 --- a/volk/gen/make_environment_init_c.py +++ /dev/null @@ -1,32 +0,0 @@ -from xml.dom import minidom - -def make_environment_init_c(dom) : - tempstring = ""; - tempstring = tempstring + "/*this file is auto_generated by volk_register.py*/\n\n"; - tempstring = tempstring + "#include<volk/volk_environment_init.h>\n" - for domarch in dom: - arch = str(domarch.attributes["name"].value); - incs = domarch.getElementsByTagName("include"); - for inc in incs: - my_inc = str(inc.firstChild.data); - tempstring = tempstring + "#ifdef LV_HAVE_" + arch.swapcase() + "\n"; - tempstring = tempstring + "#include<" + my_inc + ">\n"; - tempstring = tempstring + "#endif\n" - tempstring = tempstring + '\n\n'; - tempstring = tempstring + "void volk_environment_init(){\n" - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - envs = domarch.getElementsByTagName("environment"); - for env in envs: - cmd = str(env.firstChild.data); - tempstring = tempstring + "#ifdef LV_HAVE_" + arch.swapcase() + "\n"; - tempstring = tempstring + " " + cmd + "\n"; - tempstring = tempstring + "#endif\n" - - tempstring = tempstring + "}\n"; - return tempstring; - - - - diff --git a/volk/gen/make_environment_init_h.py b/volk/gen/make_environment_init_h.py deleted file mode 100644 index 0b0f35d61..000000000 --- a/volk/gen/make_environment_init_h.py +++ /dev/null @@ -1,18 +0,0 @@ -from xml.dom import minidom - -def make_environment_init_h() : - tempstring = ""; - tempstring = tempstring + "/*this file is auto_generated by volk_register.py*/\n\n"; - tempstring = tempstring + "#ifndef INCLUDE_LIBVECTOR_ENVIRONMENT_INIT_H\n"; - tempstring = tempstring + "#define INCLUDE_LIBVECTOR_ENVIRONMENT_INIT_H\n"; - tempstring = tempstring + "\n"; - tempstring = tempstring + "#include <volk/volk_common.h>\n\n"; - tempstring = tempstring + "__VOLK_DECL_BEGIN\n"; - tempstring = tempstring + "void volk_environment_init();\n"; - tempstring = tempstring + "__VOLK_DECL_END\n"; - tempstring = tempstring + "#endif\n" - return tempstring; - - - - diff --git a/volk/gen/make_h.py b/volk/gen/make_h.py deleted file mode 100644 index cf8987c39..000000000 --- a/volk/gen/make_h.py +++ /dev/null @@ -1,38 +0,0 @@ -from xml.dom import minidom -from volk_regexp import * - -def make_h(funclist, arched_arglist) : - tempstring = ""; - tempstring = tempstring + '/*this file is auto generated by make_h.py*/\n'; - - tempstring = tempstring + '\n#ifndef INCLUDED_VOLK_RUNTIME'; - tempstring = tempstring + '\n#define INCLUDED_VOLK_RUNTIME'; - tempstring = tempstring + '\n\n#include<volk/volk_typedefs.h>\n'; - tempstring = tempstring + '#include<volk/volk_config_fixed.h>\n'; - tempstring = tempstring + '#include<volk/volk_common.h>\n'; - tempstring = tempstring + '#include<volk/volk_complex.h>\n'; - tempstring = tempstring + '__VOLK_DECL_BEGIN\n'; - - tempstring = tempstring + '\n'; - - tempstring += """ -struct volk_func_desc { - const char **indices; - const int *arch_defs; - const int n_archs; -}; - -VOLK_API unsigned int volk_get_alignment(void); - -""" - for i in range(len(funclist)): - tempstring += "extern VOLK_API " + replace_volk.sub("p", funclist[i]) + " " + funclist[i] + ";\n" - tempstring += "extern VOLK_API void %s_manual%s;\n" % (funclist[i], arched_arglist[i]) - tempstring = strip_trailing(tempstring, " {") - tempstring += "extern VOLK_API struct volk_func_desc %s_get_func_desc(void);\n" % (funclist[i]) - - tempstring = tempstring + '__VOLK_DECL_END\n'; - tempstring = tempstring + "#endif /*INCLUDED_VOLK_RUNTIME*/\n"; - - return tempstring; - diff --git a/volk/gen/make_machines_c.py b/volk/gen/make_machines_c.py deleted file mode 100644 index f19da4ae4..000000000 --- a/volk/gen/make_machines_c.py +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program 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, see <http://www.gnu.org/licenses/>. -# - -from volk_regexp import * - -def make_machines_c(machines): - tempstring = r""" -// This file is automatically generated by make_machines_c.py. -// Do not edit this file. - -#include <volk/volk_common.h> -#include <volk/volk_typedefs.h> -#include "volk_machines.h" - -struct volk_machine *volk_machines[] = { -""" - for machine in machines: - tempstring += """#if LV_MACHINE_""" + machine.swapcase() + "\n" - tempstring += "&volk_machine_" + machine - tempstring += "," - tempstring += "\n#endif\n" - - tempstring += r""" -}; -unsigned int n_volk_machines = sizeof(volk_machines)/sizeof(*volk_machines); -""" - return tempstring diff --git a/volk/gen/make_machines_h.py b/volk/gen/make_machines_h.py deleted file mode 100644 index d2374120b..000000000 --- a/volk/gen/make_machines_h.py +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program 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, see <http://www.gnu.org/licenses/>. -# - -from volk_regexp import * - -def make_machines_h(functions, machines, archs): - tempstring = r""" -// This file is automatically generated by make_machines_h.py. -// Do not edit this file. - -#ifndef INCLUDED_LIBVOLK_MACHINES_H -#define INCLUDED_LIBVOLK_MACHINES_H - -#include <volk/volk_common.h> -#include <volk/volk_typedefs.h> - -__VOLK_DECL_BEGIN - -struct volk_machine { - const unsigned int caps; //capabilities (i.e., archs compiled into this machine, in the volk_get_lvarch format) - const char *name; - const unsigned int alignment; //the maximum byte alignment required for functions in this library -""" - for function in functions: - tempstring += " const char *%s_name;\n"%function - tempstring += " const char *%s_indices[%d];\n"%(function, len(archs)) - tempstring += " const int %s_arch_defs[%d];\n"%(function, len(archs)) - tempstring += " const %s %s_archs[%d];\n"%(replace_volk.sub("p", function), function, len(archs)) - tempstring += " const int %s_n_archs;\n"%function - - tempstring += r"""}; - -""" - for machine in machines: - tempstring += """#if LV_MACHINE_""" + machine.swapcase() + "\n" - tempstring += "extern struct volk_machine volk_machine_" + machine + ";\n" - tempstring += """#endif\n""" - - tempstring += r""" - -__VOLK_DECL_END - -#endif //INCLUDED_LIBVOLK_MACHINES_H""" - - return tempstring diff --git a/volk/gen/make_makefile_am.py b/volk/gen/make_makefile_am.py deleted file mode 100644 index 880ce4094..000000000 --- a/volk/gen/make_makefile_am.py +++ /dev/null @@ -1,123 +0,0 @@ -# -# Copyright 2010-2011 Free Software Foundation, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program 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, see <http://www.gnu.org/licenses/>. -# - -from xml.dom import minidom - -def make_makefile_am(dom, machines, archflags_dict): - tempstring = r""" -# This file is automatically generated by make_makefile_am.py. -# Do not edit this file. - -include $(top_srcdir)/Makefile.common - -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) \ - -I$(top_gendir)/include \ - -I$(top_srcdir)/include \ - -Dvolk_EXPORTS \ - -fvisibility=hidden \ - $(WITH_INCLUDES) - -lib_LTLIBRARIES = \ - libvolk.la - -EXTRA_DIST = \ - volk_rank_archs.h \ - gcc_x86_cpuid.h - -# ---------------------------------------------------------------- -# The main library -# ---------------------------------------------------------------- - -libvolk_la_SOURCES = \ - $(platform_CODE) \ - $(top_gendir)/lib/volk.c \ - $(top_gendir)/lib/volk_cpu.c \ - volk_rank_archs.c \ - volk_prefs.c \ - $(top_gendir)/lib/volk_machines.c - -if LV_HAVE_ORC -volk_orc_CFLAGS = -DLV_HAVE_ORC=1 -volk_orc_LDFLAGS = $(ORC_LDFLAGS) -lorc-0.4 -volk_orc_LIBADD = ../orc/libvolk_orc.la -else -volk_orc_CFLAGS = -volk_orc_LDFLAGS = -volk_orc_LIBADD = -endif - -libvolk_la_CPPFLAGS = $(AM_CPPFLAGS) $(volk_orc_CFLAGS) -libvolk_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 $(volk_orc_LDFLAGS) -libvolk_la_LIBADD = $(volk_orc_LIBADD) - -noinst_LTLIBRARIES = - -""" - - #here be dragons - for machine_name in machines: - tempstring += "if LV_MACHINE_" + machine_name.swapcase() + "\n" - tempstring += "libvolk_" + machine_name + "_la_SOURCES = $(top_gendir)/lib/volk_machine_" + machine_name + ".c\n" - tempstring += "libvolk_" + machine_name + "_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_gendir)/include $(volk_orc_CFLAGS) " - for arch in machines[machine_name]: - if archflags_dict[arch] != "none": - tempstring += "-" + archflags_dict[arch] + " " - - tempstring += "\nnoinst_LTLIBRARIES += libvolk_" + machine_name + ".la " - tempstring += "\nlibvolk_la_LIBADD += libvolk_" + machine_name + ".la\n" - tempstring += "libvolk_la_CPPFLAGS += -DLV_MACHINE_" + machine_name.swapcase() + " \n" - tempstring += "endif\n" - - - tempstring += r""" - -# ---------------------------------------------------------------- -# The QA library. Note libvolk.la in LIBADD -# ---------------------------------------------------------------- -#libvolk_qa_la_SOURCES = \ -# qa_utils.cc - -#libvolk_qa_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 -lboost - -#libvolk_qa_la_LIBADD = \ -# libvolk.la \ -# libvolk_runtime.la - -# ---------------------------------------------------------------- -# headers that don't get installed -# ---------------------------------------------------------------- -noinst_HEADERS = \ - $(top_gendir)/lib/volk_init.h \ - $(top_gendir)/lib/volk_machines.h \ - $(top_gendir)/lib/volk_environment_init.h \ - qa_utils.h - -# ---------------------------------------------------------------- -# Our test program -# ---------------------------------------------------------------- -noinst_PROGRAMS = \ - testqa - -testqa_SOURCES = testqa.cc qa_utils.cc -testqa_CPPFLAGS = -DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN $(AM_CPPFLAGS) -testqa_LDFLAGS = $(BOOST_UNIT_TEST_FRAMEWORK_LIB) -testqa_LDADD = \ - libvolk.la -""" - - - return tempstring diff --git a/volk/gen/make_proccpu_sim.py b/volk/gen/make_proccpu_sim.py deleted file mode 100644 index e2c8123e5..000000000 --- a/volk/gen/make_proccpu_sim.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from xml.dom import minidom - -def make_proccpu_sim(dom) : - tempstring = ""; - tempstring = tempstring + "/*this file is auto_generated by volk_register.py*/\n\n"; - tempstring = tempstring + "#include <volk/volk_cpu.h>\n" - tempstring = tempstring + "#include <stdio.h>\n" - tempstring = tempstring + "\n\n" - - tempstring = tempstring + "void test_append(char* buf, int val, char* newkey){\n"; - tempstring = tempstring + " if(val==1){\n"; - tempstring = tempstring + " sprintf(buf, \"%s %s\", buf, newkey);\n"; - tempstring = tempstring + " }\n"; - tempstring = tempstring + "}\n"; - tempstring = tempstring + "\n\n"; - - tempstring = tempstring + "int main() {\n"; - tempstring = tempstring + " volk_cpu_init();\n"; - tempstring = tempstring + " char buf[2048];\n"; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " test_append(buf, volk_cpu.has_" + arch + "(), \"" + arch + "\");\n" - tempstring = tempstring + " printf(\"%s\\n\", buf);\n" - tempstring = tempstring + "}\n" - return tempstring; diff --git a/volk/gen/make_set_simd.py b/volk/gen/make_set_simd.py deleted file mode 100644 index 8334487d7..000000000 --- a/volk/gen/make_set_simd.py +++ /dev/null @@ -1,166 +0,0 @@ -# -# Copyright 2010 Free Software Foundation, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program 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, see <http://www.gnu.org/licenses/>. -# - -from xml.dom import minidom - -def make_set_simd(dom, machines) : - tempstring = ""; - tempstring = tempstring +'dnl this file is auto generated by volk_register.py\n\n'; - - tempstring = tempstring +'\ndnl define arch checks\n'; - for domarch in dom: - if str(domarch.attributes["type"].value) != "all": - arch = str(domarch.attributes["name"].value); - flag = domarch.getElementsByTagName("flag"); - flag = str(flag[0].firstChild.data); - tempstring = tempstring + "AC_DEFUN([_TRY_ADD_" + arch.swapcase() + "],\n"; - tempstring = tempstring + "[\n"; - tempstring = tempstring + " LF_CHECK_CC_FLAG([-" + flag + "])\n"; - tempstring = tempstring + " LF_CHECK_CXX_FLAG([-" + flag + "])\n"; - tempstring = tempstring + "])\n"; - - tempstring = tempstring +'\ndnl main set_simd_flags\n'; - tempstring = tempstring + "AC_DEFUN([LV_SET_SIMD_FLAGS],\n"; - tempstring = tempstring + "[\n"; - #tempstring = tempstring + " AC_REQUIRE([GR_SET_MD_CPU])\n"; - tempstring = tempstring + " AC_SUBST(LV_CXXFLAGS)\n"; - tempstring = tempstring + " indCC=no\n"; - tempstring = tempstring + " indCXX=no\n"; - tempstring = tempstring + " indLV_ARCH=no\n"; - tempstring = tempstring + " AC_ARG_WITH(lv_arch,\n"; - tempstring = tempstring + " AC_HELP_STRING([--with-lv_arch=ARCH],[set volk hardware speedups as space separated string with elements from the following list("; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + arch + ", " - tempstring = tempstring[0:len(tempstring) - 2]; - - tempstring = tempstring + ")]),\n"; - tempstring = tempstring + " [cf_with_lv_arch=\"$withval\"],\n"; - tempstring = tempstring + " [cf_with_lv_arch=\"\"])\n"; - if str(domarch.attributes["type"].value) == "all": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " AC_DEFINE(LV_MAKE_" + arch.swapcase() + ", 1, [always set "+ arch + "!])\n"; - tempstring = tempstring + " ADDONS=\"\"\n"; - tempstring = tempstring + " BUILT_ARCHS=\"\"\n"; - #tempstring = tempstring + " _MAKE_FAKE_PROCCPU\n"; - tempstring = tempstring + " OVERRULE_FLAG=\"no\"\n"; - tempstring = tempstring + " if test -z \"$cf_with_lv_arch\"; then\n"; - tempstring = tempstring + " cf_with_lv_arch=\""; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + arch + " "; - tempstring = tempstring[0:-1] + "\"\n"; - tempstring = tempstring + " OVERRULE_FLAG=\"yes\"\n"; - tempstring = tempstring + " fi\n"; - - tempstring = tempstring +'\ndnl init LV_MAKE_XXX and then try to add archs\n'; - for domarch in dom: - if str(domarch.attributes["type"].value) != "all": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " LV_MAKE_" + arch.swapcase() + "=no\n"; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - atype = str(domarch.attributes["type"].value); - if atype != "all": - tempstring = tempstring + " _TRY_ADD_" + arch.swapcase() + "\n"; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - atype = str(domarch.attributes["type"].value); - tempstring = tempstring +'\ndnl add in flags for arch ' + arch + '\n'; - overrule = domarch.getElementsByTagName("overrule"); - if overrule: - overrule = str(overrule[0].firstChild.data); - else: - overrule = ""; - overrule_val = domarch.getElementsByTagName("overrule_val"); - if overrule_val: - overrule_val = str(overrule_val[0].firstChild.data); - else: - overrule_val = ""; - flag = domarch.getElementsByTagName("flag"); - flag = str(flag[0].firstChild.data); - if atype != "all": - tempstring = tempstring + " for i in $lf_CXXFLAGS\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X-" + flag +"; then\n"; - tempstring = tempstring + " indCXX=yes\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " for i in $lf_CFLAGS\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X-" + flag +"; then\n"; - tempstring = tempstring + " indCC=yes\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " for i in $cf_with_lv_arch\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X" + arch + "; then\n"; - tempstring = tempstring + " indLV_ARCH=yes\n" - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " if test -n \"" + overrule + "\" && test \"$" + overrule + "\" == \"" + overrule_val + "\" && test \"$OVERRULE_FLAG\" == \"yes\" && test \"$indLV_ARCH\" == \"yes\"; then\n" - tempstring = tempstring + " indLV_ARCH=no\n" - tempstring = tempstring + " fi\n" - - tempstring = tempstring + " if test \"$indCC\" == \"yes\" && test \"$indCXX\" == \"yes\" && test \"$indLV_ARCH\" == \"yes\"; then\n" - - #tempstring = tempstring + " ADDONS=\"${ADDONS} -" + flag + "\"\n"; - tempstring = tempstring + " BUILT_ARCHS=\"${BUILT_ARCHS} " + arch + "\"\n"; - tempstring = tempstring + " LV_MAKE_" + arch.swapcase() + "=yes\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " indCC=no\n" - tempstring = tempstring + " indCXX=no\n" - tempstring = tempstring + " indLV_ARCH=no\n" - else: - tempstring = tempstring + " for i in $cf_with_lv_arch\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X" + arch + "; then\n"; - tempstring = tempstring + " indLV_ARCH=yes\n" - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " if test -n \"" + overrule + "\" && test \"$" + overrule + "\" == \"" + overrule_val + "\" && test \"$OVERRULE_FLAG\" == \"yes\" && test \"$indLV_ARCH\" == \"yes\"; then\n" - tempstring = tempstring + " indLV_ARCH=no\n" - tempstring = tempstring + " fi\n" - tempstring = tempstring + " if test \"$indLV_ARCH\" == \"yes\"; then\n" - tempstring = tempstring + " LV_MAKE_" + arch.swapcase() + "=yes\n"; - tempstring = tempstring + " BUILT_ARCHS=\"${BUILT_ARCHS} " + arch + "\"\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " indLV_ARCH=no\n" - - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " AM_CONDITIONAL(LV_MAKE_" + arch.swapcase() + ", test \"$LV_MAKE_" + arch.swapcase() + "\" == \"yes\")\n"; - - tempstring += "\n" - #now we can define the machines we're compiling - for machine_name in machines: - tempstring += " AM_CONDITIONAL(LV_MACHINE_" + machine_name.swapcase() + ", " - marchlist = machines[machine_name] - for march in marchlist: - tempstring += "test \"$LV_MAKE_" + march.swapcase() + "\" == \"yes\" && " - - tempstring += "test true)\n" #just so we don't have to detect the last one in the group, i know - tempstring = tempstring + " LV_CXXFLAGS=\"${LV_CXXFLAGS} ${ADDONS}\"\n" - tempstring = tempstring + "])\n" - - return tempstring; - - diff --git a/volk/gen/make_typedefs.py b/volk/gen/make_typedefs.py deleted file mode 100644 index 09221d2ef..000000000 --- a/volk/gen/make_typedefs.py +++ /dev/null @@ -1,23 +0,0 @@ -from xml.dom import minidom -import string -from volk_regexp import * - - - -def make_typedefs(funclist, retlist, my_argtypelist) : - tempstring = ""; - tempstring = tempstring + '/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '\n#ifndef INCLUDED_VOLK_TYPEDEFS'; - tempstring = tempstring + '\n#define INCLUDED_VOLK_TYPEDEFS\n'; - tempstring = tempstring + '\n\n#include<inttypes.h>\n'; - tempstring = tempstring + '#include<volk/volk_complex.h>\n'; - - tempstring = tempstring + '\n'; - - for i in range(len(funclist)): - tempstring = tempstring + "typedef " + retlist[i] +" (*" + replace_volk.sub("p", funclist[i]) + ")(" + my_argtypelist[i] + ");\n"; - - tempstring = tempstring + "#endif /*INCLUDED_VOLK_TYPEDEFS*/\n"; - - return tempstring; diff --git a/volk/gen/volk_arch_defs.py b/volk/gen/volk_arch_defs.py new file mode 100644 index 000000000..41154d5a7 --- /dev/null +++ b/volk/gen/volk_arch_defs.py @@ -0,0 +1,92 @@ +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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, see <http://www.gnu.org/licenses/>. +# + +archs = list() +arch_dict = dict() + +#TODO enable this when we are ready +create_unaligned_archs = False + +class arch_class: + def __init__(self, flags, checks, **kwargs): + for key, cast, failval in ( + ('name', str, None), + ('environment', str, None), + ('include', str, None), + ('alignment', int, 1) + ): + try: setattr(self, key, cast(kwargs[key])) + except: setattr(self, key, failval) + self.checks = checks + assert(self.name) + self._flags = flags + + def is_supported(self, compiler): + if not self._flags.keys(): return True + return compiler in self._flags.keys() + + def get_flags(self, compiler): + try: return self._flags[compiler] + except KeyError: return list() + + def __repr__(self): return self.name + +def register_arch(**kwargs): + arch = arch_class(**kwargs) + archs.append(arch) + arch_dict[arch.name] = arch + if arch.alignment > 1 and create_unaligned_archs: + kwargs['name'] += '_u' + kwargs['alignment'] = 1 + register_arch(**kwargs) + +######################################################################## +# register the arches +######################################################################## +#TODO skip the XML and put it here +from xml.dom import minidom +import os +gendir = os.path.dirname(__file__) +archs_xml = minidom.parse(os.path.join(gendir, 'archs.xml')).getElementsByTagName('arch') +for arch_xml in archs_xml: + kwargs = dict() + for attr in arch_xml.attributes.keys(): + kwargs[attr] = arch_xml.attributes[attr].value + for node in arch_xml.childNodes: + try: + name = node.tagName + val = arch_xml.getElementsByTagName(name)[0].firstChild.data + kwargs[name] = val + except: pass + checks = list() + for check_xml in arch_xml.getElementsByTagName("check"): + name = check_xml.attributes["name"].value + params = list() + for param_xml in check_xml.getElementsByTagName("param"): + params.append(param_xml.firstChild.data) + checks.append([name, params]) + flags = dict() + for flag_xml in arch_xml.getElementsByTagName("flag"): + name = flag_xml.attributes["compiler"].value + if not flags.has_key(name): flags[name] = list() + flags[name].append(flag_xml.firstChild.data) + #force kwargs keys to be of type str, not unicode for py25 + kwargs = dict((str(k), v) for k, v in kwargs.iteritems()) + register_arch(flags=flags, checks=checks, **kwargs) + +if __name__ == '__main__': + print archs diff --git a/volk/gen/volk_compile_utils.py b/volk/gen/volk_compile_utils.py new file mode 100644 index 000000000..cf1357375 --- /dev/null +++ b/volk/gen/volk_compile_utils.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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, see <http://www.gnu.org/licenses/>. +# + +import optparse +import volk_arch_defs +import volk_machine_defs + +def do_arch_flags_list(compiler): + output = list() + for arch in volk_arch_defs.archs: + if not arch.is_supported(compiler): continue + fields = [arch.name] + arch.get_flags(compiler) + output.append(','.join(fields)) + print ';'.join(output) + +def do_machines_list(arch_names): + output = list() + for machine in volk_machine_defs.machines: + machine_arch_set = set(machine.arch_names) + if set(arch_names).intersection(machine_arch_set) == machine_arch_set: + output.append(machine.name) + print ';'.join(output) + +def do_machine_flags_list(compiler, machine_name): + output = list() + machine = volk_machine_defs.machine_dict[machine_name] + for arch in machine.archs: + output.extend(arch.get_flags(compiler)) + print ' '.join(output) + +def main(): + parser = optparse.OptionParser() + parser.add_option('--mode', type='string') + parser.add_option('--compiler', type='string') + parser.add_option('--archs', type='string') + parser.add_option('--machine', type='string') + (opts, args) = parser.parse_args() + + if opts.mode == 'arch_flags': return do_arch_flags_list(opts.compiler.lower()) + if opts.mode == 'machines': return do_machines_list(opts.archs.split(';')) + if opts.mode == 'machine_flags': return do_machine_flags_list(opts.compiler.lower(), opts.machine) + +if __name__ == '__main__': main() diff --git a/volk/gen/volk_kernel_defs.py b/volk/gen/volk_kernel_defs.py new file mode 100644 index 000000000..52cdb684c --- /dev/null +++ b/volk/gen/volk_kernel_defs.py @@ -0,0 +1,224 @@ +# +# Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import os +import re +import sys +import glob + +from volk_arch_defs import archs + +remove_after_underscore = re.compile("_.*"); +space_remove = re.compile(" "); +leading_space_remove = re.compile("^ *"); +replace_arch = re.compile(", const char\* arch"); +replace_bracket = re.compile(" {"); +replace_volk = re.compile("volk"); + +def strip_trailing(tostrip, stripstr): + lindex = tostrip.rfind(stripstr) + tostrip = tostrip[0:lindex] + tostrip[lindex:len(tostrip)].replace(stripstr, ""); + return tostrip + +srcdir = os.path.dirname(os.path.dirname(__file__)) +hdr_files = glob.glob(os.path.join(srcdir, "include/volk/*.h")) + +datatypes = []; +functions = []; + +for line in hdr_files: + subline = re.search(".*_(a|u)\.h.*", os.path.basename(line)) + if subline: + subsubline = re.search("(?<=volk_).*", subline.group(0)); + if subsubline: + dtype = remove_after_underscore.sub("", subsubline.group(0)); + subdtype = re.search("[0-9]+[A-z]+", dtype); + if subdtype: + datatypes.append(subdtype.group(0)); + + +datatypes = set(datatypes); + +for line in hdr_files: + for dt in datatypes: + if dt in line: + subline = re.search("(volk_" + dt +"_.*(a|u).*\.h)", line); + if subline: + + subsubline = re.search(".+(?=\.h)", subline.group(0)); + functions.append(subsubline.group(0)); + +archs_or = "(" +for arch in archs: + archs_or = archs_or + arch.name.upper() + "|"; +archs_or = archs_or[0:len(archs_or)-1]; +archs_or = archs_or + ")"; + +taglist = []; +fcountlist = []; +arched_arglist = []; +retlist = []; +my_arglist = []; +my_argtypelist = []; +for func in functions: + tags = []; + fcount = []; + infile_source = open(os.path.join(srcdir, 'include', 'volk', func + ".h")) + begun_name = 0; + begun_paren = 0; + sourcefile = infile_source.readlines(); + infile_source.close(); + for line in sourcefile: +#FIXME: make it work for multiple #if define()s + archline = re.search("^\#if.*?LV_HAVE_" + archs_or + ".*", line); + if archline: + arch = archline.group(0); + archline = re.findall(archs_or + "(?=( |\n|&))", line); + if archline: + archsublist = []; + for tup in archline: + archsublist.append(tup[0]); + fcount.append(archsublist); + testline = re.search("static inline.*?" + func, line); + if (not testline): + continue + tagline = re.search(func + "_.+", line); + if tagline: + tag = re.search("(?<=" + func + "_)\w+(?= *\()",line); + if tag: + tag = re.search("\w+", tag.group(0)); + if tag: + tags.append(tag.group(0)); + + + if begun_name == 0: + retline = re.search(".+(?=" + func + ")", line); + if retline: + ret = retline.group(0); + + + + + subline = re.search(func + ".*", line); + if subline: + subsubline = re.search("\(.*?\)", subline.group(0)); + if subsubline: + args = subsubline.group(0); + + else: + begun_name = 1; + subsubline = re.search("\(.*", subline.group(0)); + if subsubline: + args = subsubline.group(0); + begun_paren = 1; + else: + if begun_paren == 1: + subline = re.search(".*?\)", line); + if subline: + args = args + subline.group(0); + begun_name = 0; + begun_paren = 0; + else: + subline = re.search(".*", line); + args = args + subline.group(0); + else: + subline = re.search("\(.*?\)", line); + if subline: + args = subline.group(0); + begun_name = 0; + else: + subline = re.search("\(.*", line); + if subline: + args = subline.group(0); + begun_paren = 1; + + replace = re.compile("static "); + ret = replace.sub("", ret); + replace = re.compile("inline "); + ret = replace.sub("", ret); + arched_args = args[args.find('(')+1:args.find(')')] + + remove = re.compile('\)|\(|{'); + rargs = remove.sub("", args); + sargs = rargs.split(','); + + + + margs = []; + atypes = []; + for arg in sargs: + temp = arg.split(" "); + margs.append(temp[-1]); + replace = re.compile(" " + temp[-1]); + atypes.append(replace.sub("", arg)); + + + my_args = "" + arg_types = "" + for arg in range(0, len(margs) - 1): + this_arg = leading_space_remove.sub("", margs[arg]); + my_args = my_args + this_arg + ", "; + this_type = leading_space_remove.sub("", atypes[arg]); + arg_types = arg_types + this_type + ", "; + + this_arg = leading_space_remove.sub("", margs[-1]); + my_args = my_args + this_arg; + this_type = leading_space_remove.sub("", atypes[-1]); + arg_types = arg_types + this_type; + my_argtypelist.append(arg_types); + + if(ret[-1] != ' '): + ret = ret + ' '; + + arched_arglist.append(arched_args); #!!!!!!!!!!! + my_arglist.append(my_args) #!!!!!!!!!!!!!!!!! + retlist.append(ret); + fcountlist.append(fcount); + taglist.append(tags); + +class kernel_class: + def __init__(self, index): + self.name = functions[index] + self.pname = self.name.replace('volk_', 'p_') + self.rettype = retlist[index] + self.arglist_defs = my_argtypelist[index] + self.arglist_namedefs = arched_arglist[index] + self.arglist_names = my_arglist[index] + self._tagdeps = fcountlist[index] + self._taglist = taglist[index] + + def get_tags(self, archs): + def is_in(x): return x.lower() in archs + taglist = list() + tagdeps = list() + for i in range(len(self._tagdeps)): + if all(map(is_in, self._tagdeps[i])): + taglist.append(self._taglist[i]) + tagdeps.append(self._tagdeps[i]) + return taglist, tagdeps + + def __repr__(self): + return self.name + +kernels = map(kernel_class, range(len(retlist))) + +if __name__ == '__main__': + print kernels diff --git a/volk/gen/volk_machine_defs.py b/volk/gen/volk_machine_defs.py new file mode 100644 index 000000000..d1a856981 --- /dev/null +++ b/volk/gen/volk_machine_defs.py @@ -0,0 +1,78 @@ +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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, see <http://www.gnu.org/licenses/>. +# + +from volk_arch_defs import arch_dict + +machines = list() +machine_dict = dict() + +class machine_class: + def __init__(self, name, archs): + self.name = name + self.archs = list() + self.arch_names = list() + for arch_name in archs: + if not arch_name: continue + arch = arch_dict[arch_name] + self.archs.append(arch) + self.arch_names.append(arch_name) + arch_name += '_u' + if arch.alignment > 1 and arch_dict.has_key(arch_name): + arch = arch_dict[arch_name] + self.archs.append(arch) + self.alignment = max(map(lambda a: a.alignment, self.archs)) + + def __repr__(self): return self.name + +def register_machine(name, archs): + for i, arch_name in enumerate(archs): + if '|' in arch_name: #handle special arch names with the '|' + for arch_sub in arch_name.split('|'): + if arch_sub: + register_machine(name+'_'+arch_sub, archs[:i] + [arch_sub] + archs[i+1:]) + else: + register_machine(name, archs[:i] + archs[i+1:]) + return + machine = machine_class(name=name, archs=archs) + machines.append(machine) + machine_dict[machine.name] = machine + +######################################################################## +# register the machines +######################################################################## +#TODO skip the XML and put it here +from xml.dom import minidom +import os +gendir = os.path.dirname(__file__) +machines_xml = minidom.parse(os.path.join(gendir, 'machines.xml')).getElementsByTagName('machine') +for machine_xml in machines_xml: + kwargs = dict() + for attr in machine_xml.attributes.keys(): + kwargs[attr] = machine_xml.attributes[attr].value + for node in machine_xml.childNodes: + try: + name = node.tagName + val = machine_xml.getElementsByTagName(name)[0].firstChild.data + kwargs[name] = val + except: pass + kwargs['archs'] = kwargs['archs'].split() + #force kwargs keys to be of type str, not unicode for py25 + kwargs = dict((str(k), v) for k, v in kwargs.iteritems()) + register_machine(**kwargs) + +if __name__ == '__main__': + print machines diff --git a/volk/gen/volk_regexp.py b/volk/gen/volk_regexp.py deleted file mode 100644 index eb4ceb54b..000000000 --- a/volk/gen/volk_regexp.py +++ /dev/null @@ -1,13 +0,0 @@ -import re - -remove_after_underscore = re.compile("_.*"); -space_remove = re.compile(" "); -leading_space_remove = re.compile("^ *"); -replace_arch = re.compile(", const char\* arch"); -replace_bracket = re.compile(" {"); -replace_volk = re.compile("volk"); - -def strip_trailing(tostrip, stripstr): - lindex = tostrip.rfind(stripstr) - tostrip = tostrip[0:lindex] + tostrip[lindex:len(tostrip)].replace(stripstr, ""); - return tostrip diff --git a/volk/gen/volk_register.py b/volk/gen/volk_register.py deleted file mode 100644 index 3a237c5ca..000000000 --- a/volk/gen/volk_register.py +++ /dev/null @@ -1,303 +0,0 @@ -#! /usr/bin/env python - -import sys -import os -import re -import glob -from xml.dom import minidom -from volk_regexp import * -from make_cpuid_c import make_cpuid_c -from make_cpuid_h import make_cpuid_h -from make_set_simd import make_set_simd -from make_config_fixed import make_config_fixed -from make_typedefs import make_typedefs -from make_environment_init_c import make_environment_init_c -from make_environment_init_h import make_environment_init_h -from make_makefile_am import make_makefile_am -from make_machines_h import make_machines_h -from make_machines_c import make_machines_c -from make_each_machine_c import make_each_machine_c -from make_c import make_c -from make_h import make_h -import copy - -#set srcdir and gendir -srcdir = os.path.dirname(os.path.dirname(__file__)) -try: gendir = sys.argv[1] -except: gendir = os.path.dirname(__file__) - -#ensure directories exist -for dir in ( - (os.path.join(gendir, 'include', 'volk')), - (os.path.join(gendir, 'lib')), - (os.path.join(gendir, 'config')) -): - if not os.path.exists(dir): os.makedirs(dir) - -outfile_set_simd = open(os.path.join(gendir, "config/lv_set_simd_flags.m4"), "w") -outfile_h = open(os.path.join(gendir, "include/volk/volk.h"), "w") -outfile_c = open(os.path.join(gendir, "lib/volk.c"), "w") -outfile_typedefs = open(os.path.join(gendir, "include/volk/volk_typedefs.h"), "w") -outfile_init_h = open(os.path.join(gendir, "lib/volk_init.h"), "w") -outfile_cpu_h = open(os.path.join(gendir, "include/volk/volk_cpu.h"), "w") -outfile_cpu_c = open(os.path.join(gendir, "lib/volk_cpu.c"), "w") -#outfile_config_in = open(os.path.join(gendir, "include/volk/volk_config.h.in"), "w") -outfile_config_fixed = open(os.path.join(gendir, "include/volk/volk_config_fixed.h"), "w") -outfile_environment_c = open(os.path.join(gendir, "lib/volk_environment_init.c"), "w") -outfile_environment_h = open(os.path.join(gendir, "lib/volk_environment_init.h"), "w") -outfile_makefile_am = open(os.path.join(gendir, "lib/Makefile.am"), "w") -outfile_machines_h = open(os.path.join(gendir, "lib/volk_machines.h"), "w") -outfile_machines_c = open(os.path.join(gendir, "lib/volk_machines.c"), "w") -hdr_files = glob.glob(os.path.join(srcdir, "include/volk/*.h")) - -datatypes = []; -functions = []; - -for line in hdr_files: - subline = re.search(".*_(a|u)\.h.*", os.path.basename(line)) - if subline: - subsubline = re.search("(?<=volk_).*", subline.group(0)); - if subsubline: - dtype = remove_after_underscore.sub("", subsubline.group(0)); - subdtype = re.search("[0-9]+[A-z]+", dtype); - if subdtype: - datatypes.append(subdtype.group(0)); - - -datatypes = set(datatypes); - -for line in hdr_files: - for dt in datatypes: - if dt in line: - subline = re.search("(volk_" + dt +"_.*(a|u).*\.h)", line); - if subline: - - subsubline = re.search(".+(?=\.h)", subline.group(0)); - functions.append(subsubline.group(0)); - -archs = []; -afile = minidom.parse(os.path.join(srcdir, "gen/archs.xml")) -filearchs = afile.getElementsByTagName("arch"); -for filearch in filearchs: - archs.append(str(filearch.attributes["name"].value)); - -for arch in archs: - a_var = re.search("^\$", arch); - if a_var: - archs.remove(arch); - -#strip out mutex archs - -archflags_dict = {} -for filearch in filearchs: - archflags_dict[str(filearch.attributes["name"].value)] = str(filearch.getElementsByTagName("flag")[0].firstChild.data) - -archalign_dict = {} -for filearch in filearchs: - alignelem = filearch.getElementsByTagName("alignment") - if(alignelem): - archalign_dict[str(filearch.attributes["name"].value)] = int(alignelem[0].firstChild.data) - -archs_or = "(" -for arch in archs: - archs_or = archs_or + arch.upper() + "|"; -archs_or = archs_or[0:len(archs_or)-1]; -archs_or = archs_or + ")"; - -#get machine list and parse to a list of machines, each with a list of archs (none of this DOM crap) -machine_str_dict = {} -mfile = minidom.parse(os.path.join(srcdir, "gen/machines.xml")) -filemachines = mfile.getElementsByTagName("machine") - -for filemachine in filemachines: - machine_str_dict[str(filemachine.attributes["name"].value)] = str(filemachine.getElementsByTagName("archs")[0].firstChild.data).split() - -#all right now you have a dict of arch lists -#next we expand it -#this is an expanded list accounting for the OR syntax -#TODO: make this work for multiple "|" machines -machines = {} -already_done = False -for machine_name in machine_str_dict: - already_done = False - marchlist = machine_str_dict[machine_name] - for march in marchlist: - or_marchs = march.split("|") - if len(or_marchs) > 1: - marchlist.remove(march) - for or_march in or_marchs: - tempmarchlist = copy.deepcopy(marchlist) - tempmarchlist.append(or_march) - machines[machine_name + "_" + or_march] = tempmarchlist - already_done = True - - if not already_done: - machines[machine_name] = marchlist - -#get the maximum alignment for all archs in a machine -machine_alignment_dict = {} -for machine in machines: - machine_alignment_dict[machine] = max((archalign_dict.get(k, 1)) for k in machines[machine]) - -#for machine in machine_alignment_dict: -# print machine + ": %d" % machine_alignment_dict[machine] - -taglist = []; -fcountlist = []; -arched_arglist = []; -retlist = []; -my_arglist = []; -my_argtypelist = []; -for func in functions: - tags = []; - fcount = []; - infile_source = open(os.path.join(srcdir, 'include', 'volk', func + ".h")) - begun_name = 0; - begun_paren = 0; - sourcefile = infile_source.readlines(); - infile_source.close(); - for line in sourcefile: -#FIXME: make it work for multiple #if define()s - archline = re.search("^\#if.*?LV_HAVE_" + archs_or + ".*", line); - if archline: - arch = archline.group(0); - archline = re.findall(archs_or + "(?=( |\n|&))", line); - if archline: - archsublist = []; - for tup in archline: - archsublist.append(tup[0]); - fcount.append(archsublist); - testline = re.search("static inline.*?" + func, line); - if (not testline): - continue - tagline = re.search(func + "_.+", line); - if tagline: - tag = re.search("(?<=" + func + "_)\w+(?= *\()",line); - if tag: - tag = re.search("\w+", tag.group(0)); - if tag: - tags.append(tag.group(0)); - - - if begun_name == 0: - retline = re.search(".+(?=" + func + ")", line); - if retline: - ret = retline.group(0); - - - - - subline = re.search(func + ".*", line); - if subline: - subsubline = re.search("\(.*?\)", subline.group(0)); - if subsubline: - args = subsubline.group(0); - - else: - begun_name = 1; - subsubline = re.search("\(.*", subline.group(0)); - if subsubline: - args = subsubline.group(0); - begun_paren = 1; - else: - if begun_paren == 1: - subline = re.search(".*?\)", line); - if subline: - args = args + subline.group(0); - begun_name = 0; - begun_paren = 0; - else: - subline = re.search(".*", line); - args = args + subline.group(0); - else: - subline = re.search("\(.*?\)", line); - if subline: - args = subline.group(0); - begun_name = 0; - else: - subline = re.search("\(.*", line); - if subline: - args = subline.group(0); - begun_paren = 1; - - replace = re.compile("static "); - ret = replace.sub("", ret); - replace = re.compile("inline "); - ret = replace.sub("", ret); - replace = re.compile("\)"); - arched_args = replace.sub(", const char* arch) {", args); - - remove = re.compile('\)|\(|{'); - rargs = remove.sub("", args); - sargs = rargs.split(','); - - - - margs = []; - atypes = []; - for arg in sargs: - temp = arg.split(" "); - margs.append(temp[-1]); - replace = re.compile(" " + temp[-1]); - atypes.append(replace.sub("", arg)); - - - my_args = "" - arg_types = "" - for arg in range(0, len(margs) - 1): - this_arg = leading_space_remove.sub("", margs[arg]); - my_args = my_args + this_arg + ", "; - this_type = leading_space_remove.sub("", atypes[arg]); - arg_types = arg_types + this_type + ", "; - - this_arg = leading_space_remove.sub("", margs[-1]); - my_args = my_args + this_arg; - this_type = leading_space_remove.sub("", atypes[-1]); - arg_types = arg_types + this_type; - my_argtypelist.append(arg_types); - - if(ret[-1] != ' '): - ret = ret + ' '; - - arched_arglist.append(arched_args); #!!!!!!!!!!! - my_arglist.append(my_args) #!!!!!!!!!!!!!!!!! - retlist.append(ret); - fcountlist.append(fcount); - taglist.append(tags); - - -outfile_cpu_h.write(make_cpuid_h(filearchs)); -outfile_cpu_h.close(); - -outfile_cpu_c.write(make_cpuid_c(filearchs)); -outfile_cpu_c.close(); - -outfile_set_simd.write(make_set_simd(filearchs, machines)); -outfile_set_simd.close(); - -outfile_config_fixed.write(make_config_fixed(filearchs)); -outfile_config_fixed.close(); - -outfile_typedefs.write(make_typedefs(functions, retlist, my_argtypelist)); -outfile_typedefs.close(); - -outfile_makefile_am.write(make_makefile_am(filearchs, machines, archflags_dict)) -outfile_makefile_am.close() - -outfile_machines_h.write(make_machines_h(functions, machines, archs)) -outfile_machines_h.close() - -outfile_machines_c.write(make_machines_c(machines)) -outfile_machines_c.close() - -outfile_c.write(make_c(machines, archs, functions, arched_arglist, my_arglist)) -outfile_c.close() - -outfile_h.write(make_h(functions, arched_arglist)) -outfile_h.close() - -for machine in machines: - machine_c_filename = os.path.join(gendir, "lib/volk_machine_" + machine + ".c") - outfile_machine_c = open(machine_c_filename, "w") - outfile_machine_c.write(make_each_machine_c(machine, machines[machine], functions, fcountlist, taglist, machine_alignment_dict[machine])) - outfile_machine_c.close() diff --git a/volk/gen/volk_tmpl_utils.py b/volk/gen/volk_tmpl_utils.py new file mode 100644 index 000000000..6c08a8213 --- /dev/null +++ b/volk/gen/volk_tmpl_utils.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# +# Copyright 2012 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import os +import re +import sys +import optparse +import volk_arch_defs +import volk_machine_defs +import volk_kernel_defs +from Cheetah import Template + +def __escape_pre_processor(code): + out = list() + for line in code.splitlines(): + m = re.match('^(\s*)#(\s*)(\w+)(.*)$', line) + if m: + p0, p1, fcn, stuff = m.groups() + conly = fcn in ('include', 'define', 'ifdef', 'ifndef', 'endif', 'elif', 'pragma') + both = fcn in ('if', 'else') + istmpl = '$' in stuff + if 'defined' in stuff: istmpl = False + if conly or (both and not istmpl): + line = '%s\\#%s%s%s'%(p0, p1, fcn, stuff) + out.append(line) + return '\n'.join(out) + +def __parse_tmpl(_tmpl, **kwargs): + defs = { + 'archs': volk_arch_defs.archs, + 'arch_dict': volk_arch_defs.arch_dict, + 'machines': volk_machine_defs.machines, + 'machine_dict': volk_machine_defs.machine_dict, + 'kernels': volk_kernel_defs.kernels, + } + defs.update(kwargs) + _tmpl = __escape_pre_processor(_tmpl) + _tmpl = """ + +/* this file was generated by volk template utils, do not edit! */ + +""" + _tmpl + return str(Template.Template(_tmpl, defs)) + +def main(): + parser = optparse.OptionParser() + parser.add_option('--input', type='string') + parser.add_option('--output', type='string') + (opts, args) = parser.parse_args() + + output = __parse_tmpl(open(opts.input).read(), args=args) + if opts.output: open(opts.output, 'w').write(output) + else: print output + +if __name__ == '__main__': main() diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt index b491f94bb..8288786c9 100644 --- a/volk/lib/CMakeLists.txt +++ b/volk/lib/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011-2012 Free Software Foundation, Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,6 +16,31 @@ # ######################################################################## +# header file detection +######################################################################## +include(CheckIncludeFile) +CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H) +if(HAVE_CPUID_H) + add_definitions(-DHAVE_CPUID_H) +endif() + +CHECK_INCLUDE_FILE(intrin.h HAVE_INTRIN_H) +if(HAVE_INTRIN_H) + add_definitions(-DHAVE_INTRIN_H) +endif() + +CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H) +if(HAVE_FENV_H) + add_definitions(-DHAVE_FENV_H) +endif() + +CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H) +if(HAVE_DLFCN_H) + add_definitions(-DHAVE_DLFCN_H) + list(APPEND volk_libraries ${CMAKE_DL_LIBS}) +endif() + +######################################################################## # Setup the compiler name ######################################################################## set(COMPILER_NAME ${CMAKE_C_COMPILER_ID}) @@ -23,235 +48,183 @@ if(MSVC) #its not set otherwise set(COMPILER_NAME MSVC) endif() +message(STATUS "Compiler name: ${COMPILER_NAME}") + if(NOT DEFINED COMPILER_NAME) message(FATAL_ERROR "COMPILER_NAME undefined. Volk build may not support this compiler.") endif() ######################################################################## -# Parse the arches xml file: -# Test each arch to see if the compiler supports the flag. -# If the test passes append the arch to the available list. +# detect x86 flavor of CPU ######################################################################## -#extract the compiler lines from the xml file using abusive python - - - -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda b: ','.join([','.join([b.attributes['name'].value,item.attributes['name'].value,item.firstChild.data]) for item in b.getElementsByTagName('remap')]), minidom.parse('${CMAKE_SOURCE_DIR}/gen/compilers.xml').getElementsByTagName('compiler')))" - - OUTPUT_VARIABLE compiler_lines OUTPUT_STRIP_TRAILING_WHITESPACE -) - -foreach(thing ${compiler_lines}) - string(REGEX REPLACE "," ";" thing_list ${thing}) - list(FIND thing_list ${COMPILER_NAME} check_val) - if(NOT ("${check_val}" STREQUAL "-1")) - string(REGEX REPLACE "${COMPILER_NAME}," ";" filter_string ${thing}) - endif() -endforeach() - +if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(i.86|x86|x86_64|amd64)$") + message(STATUS "x86* CPU detected") + set(CPU_IS_x86 TRUE) +endif() -#extract compiler prefixes from the xml file using abusive python +######################################################################## +# determine passing architectures based on compile flag tests +######################################################################## execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda b: ','.join([','.join([b.attributes['name'].value,item.firstChild.data]) for item in b.getElementsByTagName('prefix')]), minidom.parse('${CMAKE_SOURCE_DIR}/gen/compilers.xml').getElementsByTagName('compiler')))" - - OUTPUT_VARIABLE compiler_prefixes OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_compile_utils.py + --mode "arch_flags" --compiler "${COMPILER_NAME}" + OUTPUT_VARIABLE arch_flag_lines OUTPUT_STRIP_TRAILING_WHITESPACE ) -foreach(thing ${compiler_prefixes}) - string(REGEX REPLACE "," ";" thing_list ${thing}) - list(FIND thing_list ${COMPILER_NAME} check_val) - if(NOT ("${check_val}" STREQUAL "-1")) - list(GET thing_list "1" prefix) +macro(check_arch arch_name) + set(flags ${ARGN}) + set(have_${arch_name} TRUE) + foreach(flag ${flags}) + include(CheckCXXCompilerFlag) + set(have_flag have${flag}) + execute_process( #make the have_flag have nice alphanum chars (just for looks/not necessary) + COMMAND ${PYTHON_EXECUTABLE} -c "import re; print(re.sub('\\W', '_', '${have_flag}'))" + OUTPUT_VARIABLE have_flag OUTPUT_STRIP_TRAILING_WHITESPACE + ) + CHECK_CXX_COMPILER_FLAG(${flag} ${have_flag}) + if (NOT ${have_flag}) + set(have_${arch_name} FALSE) + endif() + endforeach(flag) + if (have_${arch_name}) + list(APPEND available_archs ${arch_name}) endif() -endforeach() - - - - -#extract the arch lines from the xml file using abusive python -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda a: '%s %s %s %s'%(a.attributes['name'].value,a.getElementsByTagName('flag')[0].firstChild.data,a.getElementsByTagName('overrule')[0].firstChild.data,a.getElementsByTagName('overrule_val')[0].firstChild.data) if (len(a.getElementsByTagName('overrule'))) else '%s %s %s %s'%(a.attributes['name'].value,a.getElementsByTagName('flag')[0].firstChild.data,'no_overrule', 'no_overrule_val'), minidom.parse('${CMAKE_SOURCE_DIR}/gen/archs.xml').getElementsByTagName('arch')))" - - OUTPUT_VARIABLE arch_lines OUTPUT_STRIP_TRAILING_WHITESPACE -) +endmacro(check_arch) +foreach(line ${arch_flag_lines}) + string(REGEX REPLACE "," ";" arch_flags ${line}) + check_arch(${arch_flags}) +endforeach(line) +macro(OVERRULE_ARCH arch reason) + message(STATUS "${reason}, Overruled arch ${arch}") + list(REMOVE_ITEM available_archs ${arch}) +endmacro(OVERRULE_ARCH) - -#set the various overrule values (see archs.xml) -#a lot of this is translating between automake and cmake -if(NOT "${CROSSCOMPILE_MULTILIB}" STREQUAL "true") - set(MD_SUBCPU ${CMAKE_SYSTEM_PROCESSOR}) - #detect 32 or 64 bit compiler - if(MD_SUBCPU MATCHES "^(i.86|x86|x86_64|amd64)$") - include(CheckTypeSize) - check_type_size("void*" SIZEOF_VOID_P BUILTIN_TYPES_ONLY) - if (${SIZEOF_VOID_P} EQUAL 8) - set(MD_SUBCPU x86_64) - else() - set(MD_SUBCPU x86) - endif() +######################################################################## +# eliminate AVX on GCC < 4.4 +# even though it accepts -mavx, as won't assemble xgetbv, which we need +######################################################################## +if(CPU_IS_x86 AND COMPILER_NAME MATCHES "GNU") + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + if(GCC_VERSION VERSION_LESS "4.4") + OVERRULE_ARCH(avx "GCC missing xgetbv") endif() endif() -if(NOT "${ORC_FOUND}" STREQUAL "TRUE") - set(LV_HAVE_ORC "no") -endif() - +######################################################################## +# implement overruling in the ORC case, +# since ORC always passes flag detection +######################################################################## +if(NOT ORC_FOUND) + OVERRULE_ARCH(orc "ORC support not found") +endif() - - - -macro(compiler_filter name flag) - set(filtered_flag ${flag}) - foreach(thing ${filter_string}) - string(REGEX REPLACE "," ";" flagmap ${thing}) - list(GET flagmap "0" key) - list(GET flagmap "1" val) - string(REGEX MATCH "^${key}$" found ${flag}) - if("${found}" STREQUAL "${key}") - string(REGEX REPLACE "^${key}$" "${val}" filtered_flag ${flag}) - endif() - endforeach() - set(${name}_flag "${prefix}${filtered_flag}") -endmacro() - - - - - - - -macro(handle_arch name flag overrule overrule_val) - - #handle overrule - if("${${overrule}}" STREQUAL "${overrule_val}") - set(have_${name} FALSE) - message(STATUS "${name} overruled") - #handle special case for none flag - elseif(${flag} STREQUAL "none") - set(have_${name} TRUE) - #otherwise test the flag(s) against the compiler - else() - include(CheckCXXCompilerFlag) - string(REGEX REPLACE "," ";" flag_list ${flag}) - set(have_${name} 1) - foreach(thing ${flag_list}) - compiler_filter(${name} ${thing}) - CHECK_CXX_COMPILER_FLAG(${${name}_flag} have_${thing}) - if(NOT (${have_${name}} AND ("${have_${thing}}" STREQUAL "1"))) - set(have_${name} 0) - endif() - endforeach() +######################################################################## +# implement overruling in the non-multilib case +# this makes things work when both -m32 and -m64 pass +######################################################################## +if(NOT CROSSCOMPILE_MULTILIB AND CPU_IS_x86) + include(CheckTypeSize) + check_type_size("void*[8]" SIZEOF_CPU BUILTIN_TYPES_ONLY) + if (${SIZEOF_CPU} EQUAL 64) + OVERRULE_ARCH(32 "CPU width is 64 bits") endif() - - if(have_${name}) - list(APPEND available_arches ${name}) + if (${SIZEOF_CPU} EQUAL 32) + OVERRULE_ARCH(64 "CPU width is 32 bits") endif() +endif() -endmacro(handle_arch) - -#create a list of available arches -foreach(arch_line ${arch_lines}) - string(REPLACE " " ";" args "${arch_line}") - handle_arch(${args}) -endforeach(arch_line) - -message(STATUS "Available arches: ${available_arches}") +######################################################################## +# done overrules! print the result +######################################################################## +message(STATUS "Available architectures: ${available_archs}") ######################################################################## -# Parse the machines xml file: -# Test each machine to see if its arch dependencies are supported. -# Build a list of supported machines and the machine definitions. +# determine available machines given the available architectures ######################################################################## -#extract the machine lines from the xml file using crazy python execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda a: '%s %s'%(a.attributes['name'].value,a.getElementsByTagName('archs')[0].firstChild.data),minidom.parse('${CMAKE_SOURCE_DIR}/gen/machines.xml').getElementsByTagName('machine')))" - OUTPUT_VARIABLE machine_lines OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_compile_utils.py + --mode "machines" --archs "${available_archs}" + OUTPUT_VARIABLE available_machines OUTPUT_STRIP_TRAILING_WHITESPACE ) -macro(handle_machine1 name) - unset(machine_flags) - string(TOUPPER LV_MACHINE_${name} machine_def) - - #check if all the arches are supported - foreach(arch ${ARGN}) - set(is_match ${have_${arch}}) - if(NOT is_match) - set(is_match FALSE) - break() - endif(NOT is_match) - set(machine_flags "${machine_flags} ${${arch}_flag}") - endforeach(arch) - - string(REGEX REPLACE "^[ \t]+" "" machine_flags "${machine_flags}") - - if(is_match) - #this is a match, append the source and set its flags - set(machine_source ${CMAKE_CURRENT_BINARY_DIR}/volk_machine_${name}.c) - set_source_files_properties(${machine_source} PROPERTIES COMPILE_FLAGS "${machine_flags}") - list(APPEND machine_sources ${machine_source}) - list(APPEND machine_defs ${machine_def}) - list(APPEND available_machines ${name}) - endif() -endmacro(handle_machine1) - -macro(handle_machine name) - set(arches ${ARGN}) - list(FIND arches "32|64" index) - if(${index} EQUAL -1) - handle_machine1(${name} ${arches}) - else() - list(REMOVE_ITEM arches "32|64") - handle_machine1(${name}_32 32 ${arches}) - handle_machine1(${name}_64 64 ${arches}) - endif() -endmacro(handle_machine) - -#setup the available machines -foreach(machine_line ${machine_lines}) - string(REPLACE " " ";" args "${machine_line}") - handle_machine(${args}) -endforeach(machine_line) +######################################################################## +# Implement machine overruling for redundant machines: +# A machine is redundant when expansion rules occur, +# and the arch superset passes configuration checks. +# When this occurs, eliminate the redundant machines +# to avoid unnecessary compilation of subset machines. +######################################################################## +foreach(arch orc 64 32) + foreach(machine_name ${available_machines}) + string(REPLACE "_${arch}" "" machine_name_no_arch ${machine_name}) + if (${machine_name} STREQUAL ${machine_name_no_arch}) + else() + list(REMOVE_ITEM available_machines ${machine_name_no_arch}) + endif() + endforeach(machine_name) +endforeach(arch) +######################################################################## +# done overrules! print the result +######################################################################## message(STATUS "Available machines: ${available_machines}") ######################################################################## # Create rules to run the volk generator ######################################################################## -#list of the generated sources -set(volk_gen_sources - ${CMAKE_BINARY_DIR}/include/volk/volk.h - ${CMAKE_BINARY_DIR}/lib/volk.c - ${CMAKE_BINARY_DIR}/lib/volk_init.h - ${CMAKE_BINARY_DIR}/include/volk/volk_typedefs.h - ${CMAKE_BINARY_DIR}/include/volk/volk_cpu.h - ${CMAKE_BINARY_DIR}/lib/volk_cpu.c - ${CMAKE_BINARY_DIR}/include/volk/volk_config_fixed.h - ${CMAKE_BINARY_DIR}/lib/volk_environment_init.c - ${CMAKE_BINARY_DIR}/lib/volk_environment_init.h - ${CMAKE_BINARY_DIR}/lib/volk_machines.h - ${CMAKE_BINARY_DIR}/lib/volk_machines.c - ${machine_sources} -) #dependencies are all python, xml, and header implementation files file(GLOB xml_files ${CMAKE_SOURCE_DIR}/gen/*.xml) file(GLOB py_files ${CMAKE_SOURCE_DIR}/gen/*.py) file(GLOB h_files ${CMAKE_SOURCE_DIR}/include/volk/*.h) -add_custom_command( - OUTPUT ${volk_gen_sources} - DEPENDS ${xml_files} ${py_files} ${h_files} - COMMAND ${PYTHON_EXECUTABLE} -B - ${CMAKE_SOURCE_DIR}/gen/volk_register.py - ${CMAKE_BINARY_DIR} -) +macro(gen_template tmpl output) + list(APPEND volk_gen_sources ${output}) + add_custom_command( + OUTPUT ${output} + DEPENDS ${xml_files} ${py_files} ${h_files} ${tmpl} + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_tmpl_utils.py + --input ${tmpl} --output ${output} ${ARGN} + ) +endmacro(gen_template) + +make_directory(${CMAKE_BINARY_DIR}/include/volk) + +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk.tmpl.c ${CMAKE_BINARY_DIR}/lib/volk.c) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_typedefs.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk_typedefs.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_cpu.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk_cpu.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_cpu.tmpl.c ${CMAKE_BINARY_DIR}/lib/volk_cpu.c) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_config_fixed.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk_config_fixed.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machines.tmpl.h ${CMAKE_BINARY_DIR}/lib/volk_machines.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machines.tmpl.c ${CMAKE_BINARY_DIR}/lib/volk_machines.c) + +foreach(machine_name ${available_machines}) + #generate machine source + set(machine_source ${CMAKE_CURRENT_BINARY_DIR}/volk_machine_${machine_name}.c) + gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machine_xxx.tmpl.c ${machine_source} ${machine_name}) + + #determine machine flags + execute_process( + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_compile_utils.py + --mode "machine_flags" --machine "${machine_name}" --compiler "${COMPILER_NAME}" + OUTPUT_VARIABLE ${machine_name}_flags OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(${machine_name}_flags) + set_source_files_properties(${machine_source} PROPERTIES COMPILE_FLAGS "${${machine_name}_flags}") + endif() + + #add to available machine defs + string(TOUPPER LV_MACHINE_${machine_name} machine_def) + list(APPEND machine_defs ${machine_def}) +endforeach(machine_name) ######################################################################## # Set local include directories first @@ -270,7 +243,7 @@ if(ORC_FOUND) #setup orc library usage include_directories(${ORC_INCLUDE_DIRS}) link_directories(${ORC_LIBRARY_DIRS}) - add_definitions(-DLV_HAVE_ORC) + list(APPEND volk_libraries ${ORC_LIBRARIES}) #setup orc functions file(GLOB orc_files ${CMAKE_SOURCE_DIR}/orc/*.orc) @@ -313,16 +286,15 @@ PROPERTIES COMPILE_DEFINITIONS "${machine_defs}") if(MSVC) #add compatibility includes for stdint types - include_directories(${CMAKE_SOURCE_DIR}/msvc) + include_directories(${CMAKE_SOURCE_DIR}/cmake/msvc) + add_definitions(-DHAVE_CONFIG_H) #compile the sources as C++ due to the lack of complex.h under MSVC set_source_files_properties(${volk_sources} PROPERTIES LANGUAGE CXX) endif() #create the volk runtime library add_library(volk SHARED ${volk_sources}) -if(ORC_FOUND) - target_link_libraries(volk ${ORC_LIBRARIES}) -endif(ORC_FOUND) +target_link_libraries(volk ${volk_libraries}) set_target_properties(volk PROPERTIES SOVERSION ${LIBVER}) set_target_properties(volk PROPERTIES DEFINE_SYMBOL "volk_EXPORTS") diff --git a/volk/lib/gcc_x86_cpuid.h b/volk/lib/gcc_x86_cpuid.h index 98eeb33a3..3c3f47b00 100644 --- a/volk/lib/gcc_x86_cpuid.h +++ b/volk/lib/gcc_x86_cpuid.h @@ -1,20 +1,20 @@ /* - * Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. + * Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. * * This file is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 3, 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. - * + * * Under Section 7 of GPL version 3, you are granted additional * permissions described in the GCC Runtime Library Exception, version * 3.1, as published by the Free Software Foundation. - * + * * You should have received a copy of the GNU General Public License and * a copy of the GCC Runtime Library Exception along with this program; * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see @@ -35,6 +35,8 @@ #define bit_XSAVE (1 << 26) #define bit_OSXSAVE (1 << 27) #define bit_AVX (1 << 28) +#define bit_F16C (1 << 29) +#define bit_RDRND (1 << 30) /* %edx */ #define bit_CMPXCHG8B (1 << 8) @@ -47,14 +49,22 @@ /* Extended Features */ /* %ecx */ #define bit_LAHF_LM (1 << 0) +#define bit_ABM (1 << 5) #define bit_SSE4a (1 << 6) -#define bit_SSE5 (1 << 11) +#define bit_XOP (1 << 11) +#define bit_LWP (1 << 15) +#define bit_FMA4 (1 << 16) +#define bit_TBM (1 << 21) /* %edx */ +#define bit_MMXEXT (1 << 22) #define bit_LM (1 << 29) #define bit_3DNOWP (1 << 30) #define bit_3DNOW (1 << 31) +/* Extended Features (%eax == 7) */ +#define bit_FSGSBASE (1 << 0) +#define bit_BMI (1 << 3) #if defined(__i386__) && defined(__PIC__) /* %ebx may be the PIC register. */ @@ -114,8 +124,8 @@ __get_cpuid_max (unsigned int __ext, unsigned int *__sig) unsigned int __eax, __ebx, __ecx, __edx; #ifndef __x86_64__ -#if __GNUC__ >= 3 /* See if we can use cpuid. On AMD64 we always can. */ +#if __GNUC__ >= 3 __asm__ ("pushf{l|d}\n\t" "pushf{l|d}\n\t" "pop{l}\t%0\n\t" diff --git a/volk/lib/testqa.cc b/volk/lib/testqa.cc index 593087f85..d0204fc01 100644 --- a/volk/lib/testqa.cc +++ b/volk/lib/testqa.cc @@ -55,7 +55,7 @@ VOLK_RUN_TESTS(volk_32f_x2_dot_prod_32f_a, 1e-4, 0, 204600, 1); VOLK_RUN_TESTS(volk_32f_x2_dot_prod_32f_u, 1e-4, 0, 204600, 1); //VOLK_RUN_TESTS(volk_32f_s32f_32f_fm_detect_32f_a, 1e-4, 2046, 10000); VOLK_RUN_TESTS(volk_32f_index_max_16u_a, 3, 0, 20460, 1); -VOLK_RUN_TESTS(volk_32f_x2_s32f_interleave_16ic_a, 1, 32768, 20460, 1); +VOLK_RUN_TESTS(volk_32f_x2_s32f_interleave_16ic_a, 1, 32767, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_interleave_32fc_a, 0, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_max_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_min_32f_a, 1e-4, 0, 20460, 1); diff --git a/volk/libvector_replace.sh b/volk/libvector_replace.sh deleted file mode 100755 index e1940c00f..000000000 --- a/volk/libvector_replace.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -cd $1 -files=`ls` -for file in $files -do - sed 's/libvector/volk/g' < $file > tempfile - sed 's/LIBVECTOR/VOLK/g' < tempfile > $file -done -for file in $files -do - echo $file > tempfile - newfile=`sed 's/libvector/volk/g' < tempfile` - if (test "$file" != "$newfile"); then - mv $file $newfile - echo "changed $file to $newfile" - fi -done diff --git a/volk/python/__init__.py b/volk/python/__init__.py deleted file mode 100644 index 7c9c4a0c6..000000000 --- a/volk/python/__init__.py +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright 2010 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. -# - -# The presence of this file turns this directory into a Python package - -# ---------------------------------------------------------------- -# Temporary workaround for ticket:181 (swig+python problem) -import sys -_RTLD_GLOBAL = 0 -try: - from dl import RTLD_GLOBAL as _RTLD_GLOBAL -except ImportError: - try: - from DLFCN import RTLD_GLOBAL as _RTLD_GLOBAL - except ImportError: - pass - -if _RTLD_GLOBAL != 0: - _dlopenflags = sys.getdlopenflags() - sys.setdlopenflags(_dlopenflags|_RTLD_GLOBAL) -# ---------------------------------------------------------------- - - -# import swig generated symbols into the volk namespace -from volk_swig import * - -# import any pure python here -# from volk_foo import bar -# from volk_baz import * - - -# ---------------------------------------------------------------- -# Tail of workaround -if _RTLD_GLOBAL != 0: - sys.setdlopenflags(_dlopenflags) # Restore original flags -# ---------------------------------------------------------------- diff --git a/volk/python/qa_square.py b/volk/python/qa_square.py deleted file mode 100755 index c74bc25ef..000000000 --- a/volk/python/qa_square.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2010 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import volk_swig as volk - -class qa_volk(gr_unittest.TestCase): - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_square_ff(self): - src_data = (-3, 4, -5.5, 2, 3) - expected_result = (9, 16, 30.25, 4, 9) - src = gr.vector_source_f(src_data) - sqr = volk.square_ff() - dst = gr.vector_sink_f() - self.tb.connect(src, sqr) - self.tb.connect(sqr, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) - -if __name__ == '__main__': - gr_unittest.main() diff --git a/volk/python/volk.i b/volk/python/volk.i deleted file mode 100644 index d678a9120..000000000 --- a/volk/python/volk.i +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 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. - */ - -%feature("autodoc", "1"); // generate python docstrings - -%include "exception.i" -%import "gnuradio.i" // the common stuff - -%{ -#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix -#include <stdexcept> -%} - -// ---------------------------------------------------------------- - -/* - * Gather all .i files in this directory together. - */ - -%{ - -// The .h files -#include <volk/volk_square_ff.h> - -%} - -// The .i files -%include <volk_square_ff.i> - diff --git a/volk/tmpl/volk.tmpl.c b/volk/tmpl/volk.tmpl.c new file mode 100644 index 000000000..c3a1544ff --- /dev/null +++ b/volk/tmpl/volk.tmpl.c @@ -0,0 +1,92 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <volk/volk_common.h> +#include "volk_machines.h" +#include <volk/volk_typedefs.h> +#include <volk/volk_cpu.h> +#include "volk_rank_archs.h" +#include <volk/volk.h> +#include <stdio.h> +#include <string.h> + +struct volk_machine *get_machine(void) { + extern struct volk_machine *volk_machines[]; + extern unsigned int n_volk_machines; + static struct volk_machine *machine = NULL; + + if(machine != NULL) return machine; + else { + unsigned int max_score = 0; + unsigned int i; + for(i=0; i<n_volk_machines; i++) { + if(!(volk_machines[i]->caps & (~volk_get_lvarch()))) { + if(volk_machines[i]->caps > max_score) { + max_score = volk_machines[i]->caps; + machine = volk_machines[i]; + } + } + } + printf("Using Volk machine: %s\n", machine->name); + return machine; + } +} + +unsigned int volk_get_alignment(void) { + return get_machine()->alignment; +} + +#for $kern in $kernels + +void get_$(kern.name)($kern.arglist_namedefs) { + $kern.name = get_machine()->$(kern.name)_archs[volk_rank_archs( + get_machine()->$(kern.name)_indices, + get_machine()->$(kern.name)_arch_defs, + get_machine()->$(kern.name)_n_archs, + get_machine()->$(kern.name)_name, + volk_get_lvarch() + )]; + $(kern.name)($kern.arglist_names); +} + +$kern.pname $kern.name = &get_$(kern.name); + +void $(kern.name)_manual($kern.arglist_namedefs, const char* arch) { + const size_t index = get_index( + get_machine()->$(kern.name)_indices, + get_machine()->$(kern.name)_n_archs, + arch + ); + get_machine()->$(kern.name)_archs[index]( + $kern.arglist_names + ); +} + +struct volk_func_desc $(kern.name)_get_func_desc(void) { + struct volk_func_desc desc = { + get_machine()->$(kern.name)_indices, + get_machine()->$(kern.name)_arch_defs, + get_machine()->$(kern.name)_n_archs + }; + return desc; +} + +#end for diff --git a/volk/tmpl/volk.tmpl.h b/volk/tmpl/volk.tmpl.h new file mode 100644 index 000000000..161579e46 --- /dev/null +++ b/volk/tmpl/volk.tmpl.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_VOLK_RUNTIME +#define INCLUDED_VOLK_RUNTIME + +#include <volk/volk_typedefs.h> +#include <volk/volk_config_fixed.h> +#include <volk/volk_common.h> +#include <volk/volk_complex.h> + +__VOLK_DECL_BEGIN + +struct volk_func_desc { + const char **indices; + const int *arch_defs; + const int n_archs; +}; + +VOLK_API unsigned int volk_get_alignment(void); + +#for $kern in $kernels +extern VOLK_API $kern.pname $kern.name; +extern VOLK_API void $(kern.name)_manual($kern.arglist_namedefs, const char* arch); +extern VOLK_API struct volk_func_desc $(kern.name)_get_func_desc(void); +#end for + +__VOLK_DECL_END + +#endif /*INCLUDED_VOLK_RUNTIME*/ diff --git a/volk/tmpl/volk_config_fixed.tmpl.h b/volk/tmpl/volk_config_fixed.tmpl.h new file mode 100644 index 000000000..e1c01ae77 --- /dev/null +++ b/volk/tmpl/volk_config_fixed.tmpl.h @@ -0,0 +1,29 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_VOLK_CONFIG_FIXED_H +#define INCLUDED_VOLK_CONFIG_FIXED_H + +#for $i, $arch in enumerate($archs) +#define LV_$(arch.name.upper()) $i +#end for + +#endif /*INCLUDED_VOLK_CONFIG_FIXED*/ diff --git a/volk/tmpl/volk_cpu.tmpl.c b/volk/tmpl/volk_cpu.tmpl.c new file mode 100644 index 000000000..81fc679cb --- /dev/null +++ b/volk/tmpl/volk_cpu.tmpl.c @@ -0,0 +1,184 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <volk/volk_cpu.h> +#include <volk/volk_config_fixed.h> +#include <stdlib.h> + +struct VOLK_CPU volk_cpu; + +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) + #define VOLK_CPU_x86 +#endif + +#if defined(VOLK_CPU_x86) + +//implement get cpuid for gcc compilers using a system or local copy of cpuid.h +#if defined(__GNUC__) + #if defined(HAVE_CPUID_H) + #include <cpuid.h> + #else + #include "gcc_x86_cpuid.h" + #endif + #define cpuid_x86(op, r) __get_cpuid(op, (unsigned int *)r+0, (unsigned int *)r+1, (unsigned int *)r+2, (unsigned int *)r+3) + + /* Return Intel AVX extended CPU capabilities register. + * This function will bomb on non-AVX-capable machines, so + * check for AVX capability before executing. + */ + #if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 + static inline unsigned long long _xgetbv(unsigned int index){ + unsigned int eax, edx; + __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); + return ((unsigned long long)edx << 32) | eax; + } + #define __xgetbv() _xgetbv(0) + #else + #define __xgetbv() 0 + #endif + +//implement get cpuid for MSVC compilers using __cpuid intrinsic +#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H) + #include <intrin.h> + #define cpuid_x86(op, r) __cpuid(((int*)r), op) + + #if defined(_XCR_XFEATURE_ENABLED_MASK) + #define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK) + #else + #define __xgetbv() 0 + #endif + +#else + #error "A get cpuid for volk is not available on this compiler..." +#endif //defined(__GNUC__) + +#endif //defined(VOLK_CPU_x86) + +static inline unsigned int cpuid_x86_bit(unsigned int reg, unsigned int op, unsigned int bit) { +#if defined(VOLK_CPU_x86) + unsigned int regs[4]; + cpuid_x86(op, regs); + return regs[reg] >> bit & 0x01; +#else + return 0; +#endif +} + +static inline unsigned int check_extended_cpuid(unsigned int val) { +#if defined(VOLK_CPU_x86) + unsigned int regs[4]; + cpuid_x86(0x80000000, regs); + return regs[0] >= val; +#else + return 0; +#endif +} + +static inline unsigned int get_avx_enabled(void) { +#if defined(VOLK_CPU_x86) + return __xgetbv() & 0x6; +#else + return 0; +#endif +} + +//neon detection is linux specific +#if defined(__arm__) && defined(__linux__) + #include <asm/hwcap.h> + #include <linux/auxvec.h> + #include <stdio.h> + #define VOLK_CPU_ARM +#endif + +static int has_neon(void){ +#if defined(VOLK_CPU_ARM) + FILE *auxvec_f; + unsigned long auxvec[2]; + unsigned int found_neon = 0; + auxvec_f = fopen("/proc/self/auxv", "rb"); + if(!auxvec_f) return 0; + + //so auxv is basically 32b of ID and 32b of value + //so it goes like this + while(!found_neon && auxvec_f) { + fread(auxvec, sizeof(unsigned long), 2, auxvec_f); + if((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_NEON)) + found_neon = 1; + } + + fclose(auxvec_f); + return found_neon; +#else + return 0; +#endif +} + +static int has_ppc(void){ +#ifdef __PPC__ + return 1; +#else + return 0; +#endif +} + +#for $arch in $archs +static int i_can_has_$arch.name (void) { + #for $check, $params in $arch.checks + if ($(check)($(', '.join($params))) == 0) return 0; + #end for + return 1; +} + +#end for + +#if defined(HAVE_FENV_H) + #include <fenv.h> + static inline void set_float_rounding(void){ + fesetround(FE_TONEAREST); + } +#elif defined(_MSC_VER) + #include <float.h> + static inline void set_float_rounding(void){ + unsigned int cwrd; + _controlfp_s(&cwrd, 0, 0); + _controlfp_s(&cwrd, _RC_NEAR, _MCW_RC); + } +#else + static inline void set_float_rounding(void){ + //do nothing + } +#endif + +void volk_cpu_init() { + #for $arch in $archs + volk_cpu.has_$arch.name = &i_can_has_$arch.name; + #end for + set_float_rounding(); +} + +unsigned int volk_get_lvarch() { + unsigned int retval = 0; + volk_cpu_init(); + #for $arch in $archs + retval += volk_cpu.has_$(arch.name)() << LV_$(arch.name.upper()); + #end for + return retval; +} diff --git a/volk/tmpl/volk_cpu.tmpl.h b/volk/tmpl/volk_cpu.tmpl.h new file mode 100644 index 000000000..4d66512e1 --- /dev/null +++ b/volk/tmpl/volk_cpu.tmpl.h @@ -0,0 +1,42 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_VOLK_CPU_H +#define INCLUDED_VOLK_CPU_H + +#include <volk/volk_common.h> + +__VOLK_DECL_BEGIN + +struct VOLK_CPU { + #for $arch in $archs + int (*has_$arch.name) (); + #end for +}; + +extern struct VOLK_CPU volk_cpu; + +void volk_cpu_init (); +unsigned int volk_get_lvarch (); + +__VOLK_DECL_END + +#endif /*INCLUDED_VOLK_CPU_H*/ diff --git a/volk/tmpl/volk_machine_xxx.tmpl.c b/volk/tmpl/volk_machine_xxx.tmpl.c new file mode 100644 index 000000000..e405bd693 --- /dev/null +++ b/volk/tmpl/volk_machine_xxx.tmpl.c @@ -0,0 +1,73 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#set $this_machine = $machine_dict[$args[0]] +#set $arch_names = $this_machine.arch_names + +#for $arch in $this_machine.archs +#define LV_HAVE_$(arch.name.upper()) 1 +#end for + +#include <volk/volk_common.h> +#include "volk_machines.h" +#include <volk/volk_config_fixed.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#for $kern in $kernels +#include <volk/$(kern.name).h> +#end for + +######################################################################## +#def make_arch_have_list($archs) +$(' | '.join(['(1 << LV_%s)'%a.name.upper() for a in $archs]))#slurp +#end def + +######################################################################## +#def make_tag_str_list($tags) +{$(', '.join(['"%s"'%a for a in $tags]))}#slurp +#end def + +######################################################################## +#def make_tag_have_list($deps) +{$(', '.join([' | '.join(['(1 << LV_%s)'%a.upper() for a in d]) for d in $deps]))}#slurp +#end def + +######################################################################## +#def make_tag_kern_list($name, $tags) +{$(', '.join(['%s_%s'%($name, a) for a in $tags]))}#slurp +#end def + +struct volk_machine volk_machine_$(this_machine.name) = { + $make_arch_have_list($this_machine.archs), + "$this_machine.name", + $this_machine.alignment, + #for $kern in $kernels + #set $taglist, $tagdeps = $kern.get_tags($arch_names) + "$kern.name", + $make_tag_str_list($taglist), + $make_tag_have_list($tagdeps), + $make_tag_kern_list($kern.name, $taglist), + $(len($taglist)), + #end for +}; diff --git a/volk/tmpl/volk_machines.tmpl.c b/volk/tmpl/volk_machines.tmpl.c new file mode 100644 index 000000000..57dd03c98 --- /dev/null +++ b/volk/tmpl/volk_machines.tmpl.c @@ -0,0 +1,34 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <volk/volk_common.h> +#include <volk/volk_typedefs.h> +#include "volk_machines.h" + +struct volk_machine *volk_machines[] = { +#for $machine in $machines +#ifdef LV_MACHINE_$(machine.name.upper()) +&volk_machine_$(machine.name), +#endif +#end for +}; + +unsigned int n_volk_machines = sizeof(volk_machines)/sizeof(*volk_machines); diff --git a/volk/tmpl/volk_machines.tmpl.h b/volk/tmpl/volk_machines.tmpl.h new file mode 100644 index 000000000..b30e600ed --- /dev/null +++ b/volk/tmpl/volk_machines.tmpl.h @@ -0,0 +1,51 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_LIBVOLK_MACHINES_H +#define INCLUDED_LIBVOLK_MACHINES_H + +#include <volk/volk_common.h> +#include <volk/volk_typedefs.h> + +__VOLK_DECL_BEGIN + +struct volk_machine { + const unsigned int caps; //capabilities (i.e., archs compiled into this machine, in the volk_get_lvarch format) + const char *name; + const unsigned int alignment; //the maximum byte alignment required for functions in this library + #for $kern in $kernels + const char *$(kern.name)_name; + const char *$(kern.name)_indices[$(len($archs))]; + const int $(kern.name)_arch_defs[$(len($archs))]; + const $(kern.pname) $(kern.name)_archs[$(len($archs))]; + const int $(kern.name)_n_archs; + #end for +}; + +#for $machine in $machines +#ifdef LV_MACHINE_$(machine.name.upper()) +extern struct volk_machine volk_machine_$(machine.name); +#endif +#end for + +__VOLK_DECL_END + +#endif //INCLUDED_LIBVOLK_MACHINES_H diff --git a/volk/tmpl/volk_typedefs.tmpl.h b/volk/tmpl/volk_typedefs.tmpl.h new file mode 100644 index 000000000..52a87242f --- /dev/null +++ b/volk/tmpl/volk_typedefs.tmpl.h @@ -0,0 +1,32 @@ +/* + * Copyright 2011-2012 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_VOLK_TYPEDEFS +#define INCLUDED_VOLK_TYPEDEFS + +#include <inttypes.h> +#include <volk/volk_complex.h> + +#for $kern in $kernels +typedef $kern.rettype (*$(kern.pname))($kern.arglist_defs); +#end for + +#endif /*INCLUDED_VOLK_TYPEDEFS*/ |