summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorJunyan He <junyan.he@linux.intel.com>2014-09-01 10:12:26 +0800
committerZhigang Gong <zhigang.gong@intel.com>2014-09-04 12:09:39 +0800
commit9cbe604a1919bcac84f9c2140e6fefc8af7fef84 (patch)
tree2506a6ce1806c67dc7f74ac232d18181ea1d84be /backend
parent48041e7824886f3773466837beddfc961a807321 (diff)
Add the gen_vector script into the libocl
This script will genenrate function defines and function prototypes for all the vector functions. Some modules need very verbose vector functions after their scalar version. We will write a template for all the scalar version and use this script the generate the vector version and append them to the template to generate the header or source file. Signed-off-by: Junyan He <junyan.he@linux.intel.com> Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com> Reviewed-by: Zhigang Gong <zhigang.gong@intel.com>
Diffstat (limited to 'backend')
-rwxr-xr-xbackend/src/libocl/script/gen_vector.py382
1 files changed, 382 insertions, 0 deletions
diff --git a/backend/src/libocl/script/gen_vector.py b/backend/src/libocl/script/gen_vector.py
new file mode 100755
index 0000000..a91dfcf
--- /dev/null
+++ b/backend/src/libocl/script/gen_vector.py
@@ -0,0 +1,382 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2012 Intel Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Zhigang Gong <zhigang.gong@linux.intel.com>
+#/
+
+# This file is to generate inline code to lower down those builtin
+# vector functions to scalar functions.
+import re
+import sys
+import os
+
+if len(sys.argv) != 4:
+ print "Invalid argument {0}".format(sys.argv)
+ print "use {0} spec_file_name output_file_name just_proto".format(sys.argv[0])
+ raise
+
+all_vector = 1,2,3,4,8,16
+
+# generate generic type sets
+def gen_vector_type(type_set, vector_set = all_vector):
+ ret = []
+ for t in type_set:
+ for i in vector_set:
+ ret.append((t, i))
+ return ret
+
+def set_vector_memspace(vector_type_set, memspace):
+ ret = []
+ if memspace == '':
+ return vector_type_set
+ for t in vector_type_set:
+ ret.append((t[0], t[1], memspace))
+ return ret
+
+# if we have 3 elements in the type tuple, we are a pointer with a memory space type
+# at the third element.
+def isPointer(t):
+ return len(t) == 3
+
+all_itype = "char","short","int","long"
+all_utype = "uchar","ushort","uint","ulong"
+all_int_type = all_itype + all_utype
+
+all_float_type = "float","double"
+all_type = all_int_type + all_float_type
+
+# all vector/scalar types
+for t in all_type:
+ exec "{0}n = [\"{0}n\", gen_vector_type([\"{0}\"])]".format(t)
+ exec "s{0} = [\"{0}\", gen_vector_type([\"{0}\"], [1])]".format(t)
+
+# Predefined type sets according to the Open CL spec.
+math_gentype = ["math_gentype", gen_vector_type(all_float_type)]
+math_gentypef = ["math_gentypef", gen_vector_type(["float"])]
+math_gentyped = ["math_gentyped", gen_vector_type(["double"])]
+
+half_native_math_gentype = ["half_native_math_gentype", gen_vector_type(["float"])]
+
+integer_gentype = ["integer_gentype", gen_vector_type(all_int_type)]
+integer_ugentype = ["integer_ugentype", gen_vector_type(all_utype)]
+integer_sgentype = ["integer_sgentype", gen_vector_type(all_int_type, [1])]
+
+fast_integer_gentype = ["fast_integer_gentype", gen_vector_type(["uint", "int"])]
+
+common_gentype = ["common_gentype", gen_vector_type(all_float_type)]
+common_gentypef = ["common_gentypef", gen_vector_type(["float"])]
+common_gentyped = ["common_gentyped", gen_vector_type(["double"])]
+
+relational_gentype = ["relational_gentype", gen_vector_type(all_type)]
+relational_igentype = ["relational_igentype", gen_vector_type(all_itype)]
+relational_ugentype = ["relational_ugentype", gen_vector_type(all_utype)]
+
+misc_gentypem = ["misc_gentypem", gen_vector_type(all_type, [2, 4, 8, 16])]
+misc_gentypen = ["misc_gentypen", gen_vector_type(all_type, [2, 4, 8, 16])]
+misc_ugentypem = ["misc_ugentypem", gen_vector_type(all_utype, [2, 4, 8, 16])]
+misc_ugentypen = ["misc_ugentypen", gen_vector_type(all_utype, [2, 4, 8, 16])]
+
+all_predefined_type = math_gentype, math_gentypef, math_gentyped, \
+ half_native_math_gentype, integer_gentype,integer_sgentype,\
+ integer_ugentype, charn, ucharn, shortn, ushortn, intn, \
+ uintn, longn, ulongn, floatn, doublen, \
+ fast_integer_gentype, common_gentype, common_gentypef, \
+ common_gentyped, relational_gentype, relational_igentype, \
+ relational_ugentype, schar, suchar, sshort, sint, suint, \
+ slong, sulong, sfloat, sdouble, misc_gentypem, \
+ misc_ugentypem, misc_gentypen, misc_ugentypen
+
+# type dictionary contains all the predefined type sets.
+type_dict = {}
+
+for t in all_predefined_type:
+ type_dict.update({t[0]:t[1]})
+
+def _prefix(prefix, dtype):
+ if dtype.count("gentype") != 0:
+ return prefix + '_' + dtype
+ return dtype
+
+memspaces = ["__local ", "__private ", "__global "]
+
+def stripMemSpace(t):
+ if t[0:2] == '__':
+ for memspace in memspaces :
+ if t[0:len(memspace)] == memspace:
+ return memspace, t[len(memspace):]
+ return '', t
+
+def check_type(types):
+ for t in types:
+ memspace, t = stripMemSpace(t)
+ if not t in type_dict:
+ print t
+ raise "found invalid type."
+
+def match_unsigned(dtype):
+ if dtype[0] == 'float':
+ return ["uint", dtype[1]]
+ if dtype[0] == 'double':
+ return ["ulong", dtype[1]]
+ if dtype[0][0] == 'u':
+ return dtype
+ return ['u' + dtype[0], dtype[1]]
+
+def match_signed(dtype):
+ if dtype[0] == 'float':
+ return ["int", dtype[1]]
+ if dtype[0] == 'double':
+ return ["long", dtype[1]]
+ if dtype[0][0] != 'u':
+ return dtype
+ return [dtype[0][1:], dtype[1]]
+
+def match_scalar(dtype):
+ return [dtype[0], 1]
+
+# The dstType is the expected type, srcType is
+# the reference type. Sometimes, the dstType and
+# srcType are different. We need to fix this issue
+# and return correct dst type.
+def fixup_type(dstType, srcType, n):
+ if dstType == srcType:
+ return dstType[n]
+
+ if dstType != srcType:
+ # scalar dst type
+ if len(dstType) == 1:
+ return dstType[0]
+ # dst is not scalar bug src is scalar
+ if len(srcType) == 1:
+ return dstType[n]
+ if dstType == integer_sgentype[1] and srcType == integer_gentype[1]:
+ return match_scalar(srcType[n])
+
+ if dstType == integer_gentype[1] and \
+ (srcType == integer_sgentype[1] or \
+ srcType == integer_ugentype[1]):
+ return dstType[n]
+
+ if dstType == integer_ugentype[1] and srcType == integer_gentype[1]:
+ return match_unsigned(srcType[n])
+
+ if dstType == relational_igentype[1] and srcType == relational_gentype[1]:
+ return match_signed(srcType[n])
+ if dstType == relational_ugentype[1] and srcType == relational_gentype[1]:
+ return match_unsigned(srcType[n])
+
+ if dstType == relational_gentype[1] and \
+ (srcType == relational_igentype[1] or \
+ srcType == relational_ugentype[1]):
+ return dstType[n]
+
+ if (len(dstType) == len(srcType)):
+ return dstType[n]
+
+ print dstType, srcType
+ raise "type mispatch"
+
+class builtinProto():
+ valueTypeStr = ""
+ functionName = ""
+ paramTypeStrs = []
+ paramCount = 0
+ outputStr = []
+ prefix = ""
+ justproto = 0
+
+ def init(self, sectionHeader, sectionPrefix, justproto):
+ self.valueTypeStr = ""
+ self.functionName = ""
+ self.paramTypeStrs = []
+ self.paramCount = 0
+ self.justproto = justproto
+ if sectionHeader != "":
+ self.outputStr = [sectionHeader]
+ else:
+ self.outputStr = []
+ if sectionPrefix != "":
+ self.prefix = sectionPrefix
+ self.indent = 0
+
+ def append(self, line, nextInit = ""):
+ self.outputStr.append(line);
+ return nextInit;
+
+ def indentSpace(self):
+ ret = ""
+ for i in range(self.indent):
+ ret += ' '
+
+ return ret
+
+ def init_from_line(self, t):
+ self.append('//{0}'.format(t))
+ line = filter(None, re.split(',| |\(', t.rstrip(')\n')))
+ self.paramCount = 0
+ stripped = 0
+ memSpace = ''
+ for i, text in enumerate(line):
+ idx = i - stripped
+ if idx == 0:
+ self.valueTypeStr = _prefix(self.prefix, line[i])
+ continue
+
+ if idx == 1:
+ self.functionName = line[i];
+ continue
+
+ if idx % 2 == 0:
+ if line[i][0] == '(':
+ tmpType = line[i][1:]
+ else:
+ tmpType = line[i]
+ if tmpType == '__local' or \
+ tmpType == '__private' or \
+ tmpType == '__global':
+ memSpace = tmpType + ' '
+ stripped += 1
+ continue
+ self.paramTypeStrs.append(memSpace + _prefix(self.prefix, tmpType))
+ memSpace = ''
+ self.paramCount += 1
+
+ def gen_proto_str_1(self, vtypeSeq, ptypeSeqs, i):
+ for n in range(0, self.paramCount):
+ ptype = fixup_type(ptypeSeqs[n], vtypeSeq, i);
+ vtype = fixup_type(vtypeSeq, ptypeSeqs[n], i);
+ # XXX FIXME now skip all double vector, as we don't
+ # defined those scalar version's prototype.
+ if ptype[0].find('double') != -1 or \
+ vtype[0].find('double') != -1:
+ return
+
+ if (n == 0):
+ formatStr = 'OVERLOADABLE {0}{1} {2} ('.format(vtype[0], vtype[1], self.functionName)
+ else:
+ formatStr += ', '
+
+ if vtype[1] == 1:
+ return
+
+ if isPointer(ptype):
+ formatStr += ptype[2]
+ pointerStr = '*'
+ else:
+ pointerStr = ''
+
+ if ptype[1] != 1:
+ formatStr += '{0}{1} {2}param{3}'.format(ptype[0], ptype[1], pointerStr, n)
+ else:
+ formatStr += '{0} {1}param{2}'.format(ptype[0], pointerStr, n)
+
+ formatStr += ')'
+ if self.justproto == "1":
+ formatStr += ';'
+ self.append(formatStr)
+ return formatStr
+ formatStr = self.append(formatStr, '{{return ({0}{1})('.format(vtype[0], vtype[1]))
+ self.indent = len(formatStr)
+ for j in range(0, vtype[1]):
+ if (j != 0):
+ formatStr += ','
+ if (j + 1) % 2 == 0:
+ formatStr += ' '
+ if j % 2 == 0:
+ formatStr = self.append(formatStr, self.indentSpace())
+
+ if self.prefix == 'relational' and self.functionName != 'bitselect' and self.functionName != 'select':
+ formatStr += '-'
+ formatStr += '{0}('.format(self.functionName)
+ for n in range(0, self.paramCount):
+ if n != 0:
+ formatStr += ', '
+
+ ptype = fixup_type(ptypeSeqs[n], vtypeSeq, i)
+ vtype = fixup_type(vtypeSeq, ptypeSeqs[n], i)
+ if vtype[1] != ptype[1]:
+ if ptype[1] != 1:
+ raise "parameter is not a scalar but has different width with result value."
+ if isPointer(ptype):
+ formatStr += '&'
+ formatStr += 'param{0}'.format(n)
+ continue
+
+ if (isPointer(ptype)):
+ formatStr += '({0} {1} *)param{2} + {3:2d}'.format(ptype[2], ptype[0], n, j)
+ else:
+ if (self.functionName == 'select' and n == 2):
+ formatStr += '({0})(param{1}.s{2:x} & (({0})1 << (sizeof({0})*8 - 1)))'.format(ptype[0], n, j)
+ else:
+ formatStr += 'param{0}.s{1:x}'.format(n, j)
+
+ formatStr += ')'
+
+ formatStr += '); }\n'
+ self.append(formatStr)
+
+ return formatStr
+
+ def output(self):
+ for line in self.outputStr:
+ print line
+
+ def output(self, outFile):
+ for line in self.outputStr:
+ outFile.write('{0}\n'.format(line))
+
+ def gen_proto_str(self):
+ check_type([self.valueTypeStr] + self.paramTypeStrs)
+ vtypeSeq = type_dict[self.valueTypeStr]
+ ptypeSeqs = []
+ count = len(vtypeSeq);
+ for t in self.paramTypeStrs:
+ memspace,t = stripMemSpace(t)
+ ptypeSeqs.append(set_vector_memspace(type_dict[t], memspace))
+ count = max(count, len(type_dict[t]))
+
+ for i in range(count):
+ formatStr = self.gen_proto_str_1(vtypeSeq, ptypeSeqs, i)
+
+ self.append("")
+
+# save the prototypes into ocl_vector.h
+specFile = open(sys.argv[1], 'r')
+headerFileName = sys.argv[2]
+tempHeader = open(headerFileName, 'a')
+isJustProto = sys.argv[3]
+
+tempHeader.write("//Begin from this part is autogenerated.\n")
+tempHeader.write("//Don't modify it manually.\n")
+
+functionProto = builtinProto()
+for line in specFile:
+ if line.isspace():
+ continue
+ if line[0] == '#':
+ if line[1] == '#':
+ sectionHeader = "//{0} builtin functions".format(line[2:].rstrip())
+ sectionPrefix=(line[2:].split())[0]
+ continue
+ functionProto.init(sectionHeader, sectionPrefix, isJustProto)
+ sectionHeader = ""
+ setionPrefix = ""
+ functionProto.init_from_line(line)
+ functionProto.gen_proto_str()
+ functionProto.output(tempHeader)
+
+tempHeader.close()