1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_SC_SOURCE_CORE_OPENCL_OPBASE_HXX
#define INCLUDED_SC_SOURCE_CORE_OPENCL_OPBASE_HXX
#include <clew/clew.h>
#include <formula/token.hxx>
#include <formula/types.hxx>
#include <memory>
#include <set>
#include <vector>
namespace formula { class DoubleVectorRefToken; }
namespace formula { class FormulaToken; }
struct ScCalcConfig;
namespace sc::opencl {
class FormulaTreeNode;
/// Exceptions
/// Failed in parsing
class UnhandledToken
{
public:
UnhandledToken( const char* m, const std::string& fn, int ln );
std::string mMessage;
std::string mFile;
int mLineNumber;
};
/// Failed in marshaling
class OpenCLError
{
public:
OpenCLError( const std::string& function, cl_int error, const std::string& file, int line );
std::string mFunction;
cl_int mError;
std::string mFile;
int mLineNumber;
};
/// Inconsistent state
class Unhandled
{
public:
Unhandled( const std::string& fn, int ln );
std::string mFile;
int mLineNumber;
};
class InvalidParameterCount
{
public:
InvalidParameterCount( int parameterCount, const std::string& file, int ln );
int mParameterCount;
std::string mFile;
int const mLineNumber;
};
// Helper macro to be used in code emitting OpenCL code for Calc functions.
// Requires the vSubArguments parameter.
#define CHECK_PARAMETER_COUNT(min, max) \
do { \
const int count = vSubArguments.size(); \
if( count < ( min ) || count > ( max )) \
throw InvalidParameterCount( count, __FILE__, __LINE__ ); \
} while( false )
typedef std::shared_ptr<FormulaTreeNode> FormulaTreeNodeRef;
class FormulaTreeNode
{
public:
explicit FormulaTreeNode( const formula::FormulaToken* ft ) : mpCurrentFormula(ft)
{
Children.reserve(8);
}
std::vector<FormulaTreeNodeRef> Children;
formula::FormulaToken* GetFormulaToken() const
{
return const_cast<formula::FormulaToken*>(mpCurrentFormula.get());
}
private:
formula::FormulaConstTokenRef mpCurrentFormula;
};
/// (Partially) abstract base class for an operand
class DynamicKernelArgument
{
public:
/// delete copy constructor
DynamicKernelArgument( const DynamicKernelArgument& ) = delete;
/// delete copy-assignment operator
const DynamicKernelArgument& operator=( const DynamicKernelArgument& ) = delete;
DynamicKernelArgument( const ScCalcConfig& config, const std::string& s, const FormulaTreeNodeRef& ft );
virtual ~DynamicKernelArgument() {}
/// Generate declaration
virtual void GenDecl( std::stringstream& ss ) const = 0;
/// When declared as input to a sliding window function
virtual void GenSlidingWindowDecl( std::stringstream& ss ) const = 0;
/// When referenced in a sliding window function
virtual std::string GenSlidingWindowDeclRef( bool = false ) const = 0;
/// Create buffer and pass the buffer to a given kernel
virtual size_t Marshal( cl_kernel, int, int, cl_program ) = 0;
virtual size_t GetWindowSize() const = 0;
/// When Mix, it will be called
virtual std::string GenDoubleSlidingWindowDeclRef( bool = false ) const;
/// When Mix, it will be called
virtual std::string GenStringSlidingWindowDeclRef( bool = false ) const;
/// Generate use/references to the argument
virtual void GenDeclRef( std::stringstream& ss ) const;
virtual void GenSlidingWindowFunction( std::stringstream& );
formula::FormulaToken* GetFormulaToken() const;
virtual std::string DumpOpName() const;
virtual void DumpInlineFun( std::set<std::string>&, std::set<std::string>& ) const;
const std::string& GetName() const;
virtual bool NeedParallelReduction() const;
/// If there's actually no argument, i.e. it expands to no code.
virtual bool IsEmpty() const { return false; }
protected:
const ScCalcConfig& mCalcConfig;
std::string mSymName;
FormulaTreeNodeRef mFormulaTree;
};
typedef std::shared_ptr<DynamicKernelArgument> DynamicKernelArgumentRef;
/// Holds an input (read-only) argument reference to a SingleVectorRef.
/// or a DoubleVectorRef for non-sliding-window argument of complex functions
/// like SumOfProduct
/// In most of the cases the argument is introduced
/// by a Push operation in the given RPN.
class VectorRef : public DynamicKernelArgument
{
public:
VectorRef( const ScCalcConfig& config, const std::string& s, const FormulaTreeNodeRef& ft, int index = 0 );
virtual ~VectorRef() override;
/// Generate declaration
virtual void GenDecl( std::stringstream& ss ) const override;
/// When declared as input to a sliding window function
virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override;
/// When referenced in a sliding window function
virtual std::string GenSlidingWindowDeclRef( bool = false ) const override;
/// Create buffer and pass the buffer to a given kernel
virtual size_t Marshal( cl_kernel, int, int, cl_program ) override;
virtual void GenSlidingWindowFunction( std::stringstream& ) override;
virtual size_t GetWindowSize() const override;
virtual std::string DumpOpName() const override;
virtual void DumpInlineFun( std::set<std::string>&, std::set<std::string>& ) const override;
const std::string& GetName() const;
cl_mem GetCLBuffer() const;
virtual bool NeedParallelReduction() const override;
protected:
// Used by marshaling
cl_mem mpClmem;
// index in multiple double vector refs that have multiple ranges
const int mnIndex;
};
/// Abstract class for code generation
class OpBase
{
public:
virtual std::string GetBottom() { return "";};
virtual std::string Gen2( const std::string&/*lhs*/,
const std::string&/*rhs*/ ) const { return "";}
static std::string Gen( std::vector<std::string>& /*argVector*/ ) { return "";};
virtual std::string BinFuncName() const { return "";};
virtual void BinInlineFun( std::set<std::string>&,
std::set<std::string>& ) { }
virtual bool takeString() const = 0;
virtual bool takeNumeric() const = 0;
// Whether DoubleRef containing more than one column is handled properly.
virtual bool canHandleMultiVector() const { return false; }
//Continue process 'Zero' or Not(like OpMul, not continue process when meet
// 'Zero'
virtual bool ZeroReturnZero() { return false;}
virtual ~OpBase() { }
};
class SlidingFunctionBase : public OpBase
{
public:
typedef std::vector<DynamicKernelArgumentRef> SubArguments;
virtual void GenSlidingWindowFunction( std::stringstream&,
const std::string&, SubArguments& ) = 0;
};
class Normal : public SlidingFunctionBase
{
public:
virtual void GenSlidingWindowFunction( std::stringstream& ss,
const std::string& sSymName, SubArguments& vSubArguments ) override;
virtual bool takeString() const override { return false; }
virtual bool takeNumeric() const override { return true; }
};
class CheckVariables : public Normal
{
public:
static void GenTmpVariables( std::stringstream& ss, const SubArguments& vSubArguments );
static void CheckSubArgumentIsNan( std::stringstream& ss,
SubArguments& vSubArguments, int argumentNum );
static void CheckAllSubArgumentIsNan( std::stringstream& ss,
SubArguments& vSubArguments );
// only check isnan
static void CheckSubArgumentIsNan2( std::stringstream& ss,
SubArguments& vSubArguments, int argumentNum, const std::string& p );
static void UnrollDoubleVector( std::stringstream& ss,
const std::stringstream& unrollstr, const formula::DoubleVectorRefToken* pCurDVR,
int nCurWindowSize );
};
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|