summaryrefslogtreecommitdiff
path: root/sc/source/core/opencl/opbase.hxx
blob: 8a15c136523b59c04698c8588abf3a4c922783c1 (plain)
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/* -*- 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 SC_OPENCL_OPBASE_HXX
#define SC_OPENCL_OPBASE_HXX

#include <sal/log.hxx>

#include "clcc/clew.h"

#include "formula/token.hxx"
#include "formula/vectortoken.hxx"
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <set>
#define ISNAN

namespace sc { namespace opencl {

class FormulaTreeNode;

/// Exceptions

/// Failed in parsing
class UnhandledToken
{
public:
    UnhandledToken(formula::FormulaToken *t,
            const char *const m, std::string fn="", int ln=0):
            mToken(t), mMessage(m), mFile(fn), mLineNumber(ln) {}
    formula::FormulaToken *mToken;
    std::string mMessage;
    std::string mFile;
    int mLineNumber;
};

/// Failed in marshaling
class OpenCLError
{
private:
    const char *strerror(cl_int i)
    {
#define CASE(val) case val: return #val
        switch (i)
        {
        CASE(CL_SUCCESS);
        CASE(CL_DEVICE_NOT_FOUND);
        CASE(CL_DEVICE_NOT_AVAILABLE);
        CASE(CL_COMPILER_NOT_AVAILABLE);
        CASE(CL_MEM_OBJECT_ALLOCATION_FAILURE);
        CASE(CL_OUT_OF_RESOURCES);
        CASE(CL_OUT_OF_HOST_MEMORY);
        CASE(CL_PROFILING_INFO_NOT_AVAILABLE);
        CASE(CL_MEM_COPY_OVERLAP);
        CASE(CL_IMAGE_FORMAT_MISMATCH);
        CASE(CL_IMAGE_FORMAT_NOT_SUPPORTED);
        CASE(CL_BUILD_PROGRAM_FAILURE);
        CASE(CL_MAP_FAILURE);
        CASE(CL_INVALID_VALUE);
        CASE(CL_INVALID_DEVICE_TYPE);
        CASE(CL_INVALID_PLATFORM);
        CASE(CL_INVALID_DEVICE);
        CASE(CL_INVALID_CONTEXT);
        CASE(CL_INVALID_QUEUE_PROPERTIES);
        CASE(CL_INVALID_COMMAND_QUEUE);
        CASE(CL_INVALID_HOST_PTR);
        CASE(CL_INVALID_MEM_OBJECT);
        CASE(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
        CASE(CL_INVALID_IMAGE_SIZE);
        CASE(CL_INVALID_SAMPLER);
        CASE(CL_INVALID_BINARY);
        CASE(CL_INVALID_BUILD_OPTIONS);
        CASE(CL_INVALID_PROGRAM);
        CASE(CL_INVALID_PROGRAM_EXECUTABLE);
        CASE(CL_INVALID_KERNEL_NAME);
        CASE(CL_INVALID_KERNEL_DEFINITION);
        CASE(CL_INVALID_KERNEL);
        CASE(CL_INVALID_ARG_INDEX);
        CASE(CL_INVALID_ARG_VALUE);
        CASE(CL_INVALID_ARG_SIZE);
        CASE(CL_INVALID_KERNEL_ARGS);
        CASE(CL_INVALID_WORK_DIMENSION);
        CASE(CL_INVALID_WORK_GROUP_SIZE);
        CASE(CL_INVALID_WORK_ITEM_SIZE);
        CASE(CL_INVALID_GLOBAL_OFFSET);
        CASE(CL_INVALID_EVENT_WAIT_LIST);
        CASE(CL_INVALID_EVENT);
        CASE(CL_INVALID_OPERATION);
        CASE(CL_INVALID_GL_OBJECT);
        CASE(CL_INVALID_BUFFER_SIZE);
        CASE(CL_INVALID_MIP_LEVEL);
        CASE(CL_INVALID_GLOBAL_WORK_SIZE);
        default:
            return "Unknown OpenCL error code";
        }
#undef CASE
    }

public:
    OpenCLError(cl_int err, std::string fn, int ln): mError(err),
    mFile(fn), mLineNumber(ln)
    {
        SAL_INFO("sc.opencl", "OpenCLError:" << mError << ": " << strerror(mError));
    }
    cl_int mError;
    std::string mFile;
    int mLineNumber;
};

/// Inconsistent state
class Unhandled
{
public:
    Unhandled(std::string fn="", int ln=0):
            mFile(fn), mLineNumber(ln) {}
    std::string mFile;
    int mLineNumber;
};

typedef boost::shared_ptr<FormulaTreeNode> FormulaTreeNodeRef;

class FormulaTreeNode
{
public:
    FormulaTreeNode(const formula::FormulaToken* ft): mpCurrentFormula(ft)
    {
        Children.reserve(8);
    }
    std::vector<FormulaTreeNodeRef> Children;
    formula::FormulaToken *GetFormulaToken(void) const
    {
        return const_cast<formula::FormulaToken*>(mpCurrentFormula.get());
    }
private:
    formula::FormulaConstTokenRef mpCurrentFormula;
};

/// (Partially) abstract base class for an operand
class DynamicKernelArgument : boost::noncopyable
{
public:
    DynamicKernelArgument(const std::string &s, FormulaTreeNodeRef ft);

    const std::string &GetNameAsString(void) const { return mSymName; }
    /// 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;

    /// When Mix, it will be called
    virtual std::string GenDoubleSlidingWindowDeclRef(bool=false) const
    { return std::string(""); }

    /// When Mix, it will be called
    virtual std::string GenStringSlidingWindowDeclRef(bool=false) const
    { return std::string(""); }

    /// Generate use/references to the argument
    virtual void GenDeclRef(std::stringstream &ss) const;

    /// Create buffer and pass the buffer to a given kernel
    virtual size_t Marshal(cl_kernel, int, int, cl_program) = 0;

    virtual ~DynamicKernelArgument() {}

    virtual void GenSlidingWindowFunction(std::stringstream &) {}
    const std::string &GetSymName(void) const { return mSymName; }
    formula::FormulaToken *GetFormulaToken(void) const;
    virtual size_t GetWindowSize(void) const = 0;
    virtual std::string DumpOpName(void) const { return std::string(""); }
    virtual void DumpInlineFun(std::set<std::string>& ,
        std::set<std::string>& ) const {}
    const std::string& GetName(void) const { return mSymName; }
    virtual bool NeedParallelReduction(void) const { return false; }

protected:
    std::string mSymName;
    FormulaTreeNodeRef mFormulaTree;
};

/// 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 std::string &s, FormulaTreeNodeRef ft, int index = 0);

    const std::string &GetNameAsString(void) const { return mSymName; }
    /// Generate declaration
    virtual void GenDecl(std::stringstream &ss) const SAL_OVERRIDE;
    /// When declared as input to a sliding window function
    virtual void GenSlidingWindowDecl(std::stringstream &ss) const SAL_OVERRIDE;

    /// When referenced in a sliding window function
    virtual std::string GenSlidingWindowDeclRef(bool=false) const SAL_OVERRIDE;

    /// Create buffer and pass the buffer to a given kernel
    virtual size_t Marshal(cl_kernel, int, int, cl_program) SAL_OVERRIDE;

    virtual ~VectorRef();

    virtual void GenSlidingWindowFunction(std::stringstream &) SAL_OVERRIDE {}
    const std::string &GetSymName(void) const { return mSymName; }
    virtual size_t GetWindowSize(void) const SAL_OVERRIDE;
    virtual std::string DumpOpName(void) const SAL_OVERRIDE { return std::string(""); }
    virtual void DumpInlineFun(std::set<std::string>& ,
        std::set<std::string>& ) const SAL_OVERRIDE {}
    const std::string& GetName(void) const { return mSymName; }
    virtual cl_mem GetCLBuffer(void) const { return mpClmem; }
    virtual bool NeedParallelReduction(void) const SAL_OVERRIDE { return false; }

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:
    typedef std::vector<std::string> ArgVector;
    typedef std::vector<std::string>::iterator ArgVectorIter;
    virtual std::string GetBottom(void) {return "";};
    virtual std::string Gen2(const std::string &/*lhs*/,
        const std::string &/*rhs*/) const {return "";}
    virtual std::string Gen(ArgVector& /*argVector*/){return "";};
    virtual std::string BinFuncName(void)const {return "";};
    virtual void BinInlineFun(std::set<std::string>& ,
        std::set<std::string>& ) {}
    virtual bool takeString() const = 0;
    virtual bool takeNumeric() const = 0;
    virtual ~OpBase() {}
};

class SlidingFunctionBase : public OpBase
{
public:
    typedef boost::shared_ptr<DynamicKernelArgument> SubArgument;
    typedef std::vector<SubArgument> SubArguments;
    virtual void GenSlidingWindowFunction(std::stringstream &,
        const std::string&, SubArguments &) = 0;
    virtual ~SlidingFunctionBase() {};
};

class Normal: public SlidingFunctionBase
{
public:
    virtual void GenSlidingWindowFunction(std::stringstream &ss,
            const std::string &sSymName, SubArguments &vSubArguments) SAL_OVERRIDE;
    virtual bool takeString() const SAL_OVERRIDE { return false; }
    virtual bool takeNumeric() const SAL_OVERRIDE { return true; }
};

class CheckVariables:public Normal
{
public:
    void GenTmpVariables(std::stringstream &ss, SubArguments &vSubArguments);
    void CheckSubArgumentIsNan(std::stringstream &ss,
            SubArguments &vSubArguments, int argumentNum);
    void CheckAllSubArgumentIsNan(std::stringstream &ss,
            SubArguments &vSubArguments);
    // only check isNan
    void CheckSubArgumentIsNan2(std::stringstream &ss,
            SubArguments &vSubArguments, int argumentNum, std::string p);
    void UnrollDoubleVector(std::stringstream &ss,
    std::stringstream &unrollstr, const formula::DoubleVectorRefToken* pCurDVR,
    int nCurWindowSize);
};

}}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */