diff options
-rw-r--r-- | volk/apps/CMakeLists.txt | 7 | ||||
-rw-r--r-- | volk/gen/volk_arch_defs.py | 70 | ||||
-rw-r--r-- | volk/gen/volk_machine_defs.py | 0 | ||||
-rw-r--r-- | volk/gen/volk_tmpl_utils.py | 51 | ||||
-rw-r--r-- | volk/gen/volk_xml_utils.py | 103 | ||||
-rw-r--r-- | volk/tmpl/volk_cpu.tmpl.c | 170 | ||||
-rw-r--r-- | volk/tmpl/volk_cpu.tmpl.h | 42 |
7 files changed, 439 insertions, 4 deletions
diff --git a/volk/apps/CMakeLists.txt b/volk/apps/CMakeLists.txt index 14291e5e3..4af935fe6 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} + PROGRAMS volk_profile + DESTINATION bin COMPONENT "volk" ) diff --git a/volk/gen/volk_arch_defs.py b/volk/gen/volk_arch_defs.py new file mode 100644 index 000000000..271fc90c7 --- /dev/null +++ b/volk/gen/volk_arch_defs.py @@ -0,0 +1,70 @@ +# +# 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 os +import copy + +archs = list() + +class arch_class: + def __init__(self, **kwargs): + for key, cast, failval in ( + ('name', str, None), + ('type', str, None), + ('no_test', bool, False), + ('val', int, None), + ('op', eval, None), + ('reg', int, None), + ('shift', int, None), + ('flag', str, None), + ('environment', str, None), + ('include', str, None), + ('alignment', int, 1), + ): + try: setattr(self, key, cast(kwargs[key])) + except: setattr(self, key, failval) + assert(self.name) + assert(self.type) + + def __repr__(self): return self.name + +def register_arch(**kwargs): + arch = arch_class(**kwargs) + archs.append(arch) + if arch.alignment > 1: + 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 +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 + register_arch(**kwargs) diff --git a/volk/gen/volk_machine_defs.py b/volk/gen/volk_machine_defs.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/volk/gen/volk_machine_defs.py diff --git a/volk/gen/volk_tmpl_utils.py b/volk/gen/volk_tmpl_utils.py new file mode 100644 index 000000000..8b00f2f1f --- /dev/null +++ b/volk/gen/volk_tmpl_utils.py @@ -0,0 +1,51 @@ +#!/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 volk_arch_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() + pponly = fcn in ('include', 'define', 'ifdef', 'ifndef', 'endif', 'elif') + both = fcn in ('if', 'else') + istmpl = '$' in stuff + if pponly 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, + } + defs.update(kwargs) + _tmpl = __escape_pre_processor(_tmpl) + return str(Template.Template(_tmpl, defs)) + +import sys +print __parse_tmpl(open(sys.argv[1]).read()) diff --git a/volk/gen/volk_xml_utils.py b/volk/gen/volk_xml_utils.py new file mode 100644 index 000000000..05c0e1193 --- /dev/null +++ b/volk/gen/volk_xml_utils.py @@ -0,0 +1,103 @@ +# +# 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/>. +# + +#this would not be necessary if we just skipped the xml part and stored the data in python + +import os +from xml.dom import minidom +import copy + +gendir = os.path.dirname(__file__) +archs_xml = minidom.parse(os.path.join(gendir, 'archs.xml')).getElementsByTagName('arch') +machines_xml = minidom.parse(os.path.join(gendir, 'machines.xml')).getElementsByTagName('machine') +compilers_xml = minidom.parse(os.path.join(gendir, 'compilers.xml')).getElementsByTagName('compiler') + +class arch_class: + def __init__(self, arch_xml): + self.name = arch_xml.attributes['name'].value + self.type = arch_xml.attributes['type'].value + for key in ('val', 'op', 'reg', 'shift', 'flag', 'environment', 'include', 'alignment'): + try: setattr(self, key, arch_xml.getElementsByTagName(key)[0].firstChild.data) + except: setattr(self, key, None) + if self.alignment is None: self.alignment = 1 + + def __repr__(self): return self.name + +def get_archs(): + adict = dict([(a.name, a) for a in map(arch_class, archs_xml)]) + udict = dict() + for name, arch in adict.iteritems(): + if arch.alignment == 1: continue + uarch = copy.deepcopy(arch) + uarch.name = arch.name + '_u' + uarch.alignment = 1 + udict[uarch.name] = uarch + adict.update(udict) + return adict + +volk_archs = get_archs() + +class machine_class: + def __init__(self, name, archlist): + self.name = name + self.archs = list() + for arch_name in archlist: + if not arch_name: continue + self.archs.append(volk_archs[arch_name]) + if volk_archs.has_key(arch_name + '_u'): + self.archs.append(volk_archs[arch_name + '_u']) + + def __repr__(self): return self.name + +def yield_machines(name, archlist): + for i, arch_name in enumerate(archlist): + if '|' in arch_name: + for arch_sub in arch_name.split('|'): + for m in yield_machines(name, archlist[:i] + [arch_sub] + archlist[i+1:]): + yield m + return + yield machine_class(name, archlist) + +def get_machines(): + mdict = dict() + for machine_xml in machines_xml: + name = machine_xml.attributes['name'].value + archlist = machine_xml.getElementsByTagName('archs')[0].firstChild.data.split() + for machine in yield_machines(name, archlist): + mdict[machine.name] = machine + return mdict + +volk_machines = get_machines() + +class compiler_class: + def __init__(self, compiler_xml): + self.name = compiler_xml.attributes['name'].value + self.prefix = compiler_xml.getElementsByTagName('prefix')[0].firstChild.data + self._remap = dict() + for remap_xml in compiler_xml.getElementsByTagName('remap'): + self._remap[remap_xml.attributes['name'].value] = remap_xml.firstChild.data + + def remap(self, option): + if not self._remap.has_key(option): return option + return self._remap[option] + + def __repr__(self): return self.name + +def get_compilers(): + return dict([(c.name, c) for c in map(compiler_class, compilers_xml)]) + +volk_compilers = get_compilers() diff --git a/volk/tmpl/volk_cpu.tmpl.c b/volk/tmpl/volk_cpu.tmpl.c new file mode 100644 index 000000000..dc24309f7 --- /dev/null +++ b/volk/tmpl/volk_cpu.tmpl.c @@ -0,0 +1,170 @@ +/* + * 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> + +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 + +#if defined(__arm__) && defined(__linux__) +#include <asm/hwcap.h> +#include <linux/auxvec.h> +#include <stdio.h> +#define LOOK_FOR_NEON +#endif + +static int has_neon(void){ +#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; +} + +static int has_ppc(void){ +#ifdef __PPC__ + return 1; +#else + return 0; +#endif +} + +#for $arch in $archs +static int i_can_has_$arch.name () { +######################################################################## + #if $arch.type == "x86" and $arch.no_test +#if defined(VOLK_CPU_x86) + return 1; +#else + return 0; +#endif +######################################################################## + #else if $arch.op == 1 +#if defined(VOLK_CPU_x86) + #set $op = hex($arch.op) + unsigned int e$(arch.reg)x = cpuid_e$(arch.reg)x ($op); + return ((e$(arch.reg)x >> $arch.shift) & 1) == $arch.val; +#else + return 0; +#endif +######################################################################## + #else if $arch.op == 0x80000001 +#if defined(VOLK_CPU_x86) + #set $op = hex($arch.op) + unsigned int extended_fct_count = cpuid_eax($op); + if (extended_fct_count < $op) + return $(arch.val)^1; + unsigned int extended_features = cpuid_e$(arch.reg)x ($op); + return ((extended_features >> $arch.shift) & 1) == $arch.val; +#else + return 0; +#endif +######################################################################## + #else if $arch.type == "powerpc" + return has_ppc(); +######################################################################## + #else if $arch.type == "arm" + return has_neon(); +######################################################################## + #else if $arch.type == "all" + return 1; +######################################################################## + #else ##$ + return 0; + #end if +} + +#end for + +void volk_cpu_init() { + #for $arch in $archs + volk_cpu.has_$arch.name = &i_can_has_$arch.name; + #end for +} + +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*/ |