source: icGREP/icgrep-devel/icgrep/kernels/streamset.h

Last change on this file was 6261, checked in by nmedfort, 4 months ago

Work on OptimizationBranch?; revisited pipeline termination

File size: 11.9 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
6#ifndef STREAMSET_H
7#define STREAMSET_H
8
9#include <llvm/IR/Type.h>  // for Type
10#include <llvm/IR/DerivedTypes.h>  // for Type
11namespace IDISA { class IDISA_Builder; }
12namespace llvm { class Value; }
13namespace llvm { class Constant; }
14
15namespace kernel {
16
17class Kernel;
18class PipelineKernel;
19class KernelBuilder;
20
21class StreamSetBuffer {
22public:
23
24    enum class BufferKind : unsigned {
25        ExternalBuffer
26        , StaticBuffer
27        , DynamicBuffer
28    };
29
30    BufferKind getBufferKind() const {
31        return mBufferKind;
32    }
33
34    llvm::Type * getType() const {
35        return mType;
36    }
37
38    llvm::Type * getBaseType() const {
39        return mBaseType;
40    }
41
42    uint64_t getNumOfStreams() const {
43        uint64_t numStreams = 1;
44        if (mBaseType->isArrayTy()) {
45            numStreams = mBaseType->getArrayNumElements();
46        }
47        return numStreams;
48    }
49
50    unsigned getAddressSpace() const {
51        return mAddressSpace;
52    }
53
54    llvm::PointerType * getPointerType() const {
55        return getType()->getPointerTo(getAddressSpace());
56    }
57
58    virtual bool hasOverflow() const = 0;
59
60    virtual size_t getOverflowCapacity(const std::unique_ptr<kernel::KernelBuilder> & b) const = 0;
61
62    virtual ~StreamSetBuffer() = 0;
63
64    llvm::Value * getHandle() const {
65        return mHandle;
66    }
67
68    virtual void allocateBuffer(const std::unique_ptr<KernelBuilder> & b) = 0;
69
70    virtual void releaseBuffer(const std::unique_ptr<KernelBuilder> & b) const = 0;
71
72    // The number of items that cam be linearly accessed from a given logical stream position.
73    virtual llvm::Value * getLinearlyAccessibleItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * fromPosition, llvm::Value * totalItems, llvm::Value * overflowItems = nullptr) const = 0;
74
75    virtual llvm::Value * getLinearlyWritableItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * fromPosition, llvm::Value * consumedItems, llvm::Value * overflowItems = nullptr) const = 0;
76
77    virtual llvm::Type * getHandleType(const std::unique_ptr<kernel::KernelBuilder> & b) const = 0;
78
79    llvm::PointerType * getHandlePointerType(const std::unique_ptr<kernel::KernelBuilder> & b) const {
80        return getHandleType(b)->getPointerTo(getAddressSpace());
81    }
82
83    virtual llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex) const;
84
85    virtual llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex) const;
86
87    virtual llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const b) const;
88
89    virtual llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b) const = 0;
90
91    virtual void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * addr) const = 0;
92
93    virtual llvm::Value * getOverflowAddress(IDISA::IDISA_Builder * const b) const = 0;
94
95    virtual void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * size) const = 0;
96
97    virtual llvm::Value * getCapacity(IDISA::IDISA_Builder * const b) const = 0;
98
99    virtual llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * absolutePosition) const;
100
101    virtual llvm::Value * getStreamLogicalBasePtr(IDISA::IDISA_Builder * const b, llvm::Value * const streamIndex, llvm::Value * blockIndex) const = 0;
102
103    void setHandle(const std::unique_ptr<KernelBuilder> & b, llvm::Value * const handle);
104
105protected:
106
107    llvm::Value * getHandle(IDISA::IDISA_Builder * const b) const;
108
109    llvm::Value * addOverflow(const std::unique_ptr<KernelBuilder> & b, llvm::Value * const bufferCapacity, llvm::Value * const overflowItems, llvm::Value * const consumedOffset = nullptr) const;
110
111    StreamSetBuffer(const BufferKind k, const std::unique_ptr<KernelBuilder> & b, llvm::Type * baseType, unsigned AddressSpace);
112
113private:
114
115    void assertValidStreamIndex(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex) const;
116
117protected:
118
119    const BufferKind                mBufferKind;
120    // Each StreamSetBuffer object is local to the Kernel (or pipeline) object at (pre-JIT) "compile time" but
121    // by sharing the same handle will refer to the same stream set at (post-JIT) run time.
122    llvm::Value *                   mHandle;
123    llvm::Type * const              mType;
124    const unsigned                  mAddressSpace;
125    llvm::Type * const              mBaseType;
126};
127
128class ExternalBuffer final : public StreamSetBuffer {
129public:
130    static inline bool classof(const StreamSetBuffer * b) {
131        return b->getBufferKind() == BufferKind::ExternalBuffer;
132    }
133
134    enum Field {BaseAddress, Capacity};
135
136    ExternalBuffer(const std::unique_ptr<KernelBuilder> & b, llvm::Type * const type, const unsigned AddressSpace = 0);
137
138    void allocateBuffer(const std::unique_ptr<KernelBuilder> & b) override;
139
140    void releaseBuffer(const std::unique_ptr<KernelBuilder> & b) const override;
141
142    llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex) const override;
143
144    llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex) const override;
145
146    llvm::Value * getStreamLogicalBasePtr(IDISA::IDISA_Builder * const b, llvm::Value * const streamIndex, llvm::Value * blockIndex) const override;
147
148    llvm::Value * getLinearlyAccessibleItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * fromPosition, llvm::Value * totalItems, llvm::Value * overflowItems = nullptr) const override;
149
150    llvm::Value * getLinearlyWritableItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * fromPosition, llvm::Value * consumedItems, llvm::Value * overflowItems = nullptr) const override;
151
152    llvm::Type * getHandleType(const std::unique_ptr<kernel::KernelBuilder> & b) const override;
153
154    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b) const override;
155
156    void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * capacity) const override;
157
158    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b) const override;
159
160    void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * addr) const override;
161
162    virtual bool hasOverflow() const override {
163        return false;
164    }
165
166    virtual size_t getOverflowCapacity(const std::unique_ptr<kernel::KernelBuilder> & b) const override;
167
168    llvm::Value * getOverflowAddress(IDISA::IDISA_Builder * const b) const override;
169
170private:
171
172    void assertValidBlockIndex(IDISA::IDISA_Builder * const b, llvm::Value * blockIndex) const;
173
174};
175
176class StaticBuffer final : public StreamSetBuffer {
177public:
178    static inline bool classof(const StreamSetBuffer * b) {
179        return b->getBufferKind() == BufferKind::StaticBuffer;
180    }
181
182    StaticBuffer(const std::unique_ptr<KernelBuilder> & b, llvm::Type * const type,
183                 const size_t capacity, const size_t overflowBlocks = 0, const unsigned AddressSpace = 0);
184
185    void allocateBuffer(const std::unique_ptr<KernelBuilder> & b) override;
186
187    void releaseBuffer(const std::unique_ptr<KernelBuilder> & b) const override;
188
189    llvm::Value * getLinearlyAccessibleItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * fromPosition, llvm::Value * const totalItems, llvm::Value * overflowItems = nullptr) const override;
190
191    llvm::Value * getLinearlyWritableItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * const fromPosition, llvm::Value * const consumedItems, llvm::Value * overflowItems = nullptr) const override;
192
193    bool hasOverflow() const override {
194        return mOverflow > 0;
195    }
196
197    size_t getOverflowCapacity(const std::unique_ptr<kernel::KernelBuilder> & b) const override;
198
199    llvm::Type * getHandleType(const std::unique_ptr<kernel::KernelBuilder> & b) const override;
200
201    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b) const override;
202
203    void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * addr) const override;
204
205    llvm::Value * getOverflowAddress(IDISA::IDISA_Builder * const b) const override;
206
207    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b) const override;
208
209    void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * capacity) const override;
210
211    llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex) const override;
212
213    llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex) const override;
214
215    llvm::Value * getStreamLogicalBasePtr(IDISA::IDISA_Builder * const b, llvm::Value * const streamIndex, llvm::Value * blockIndex) const override;
216
217    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * absolutePosition) const override;
218
219    size_t getCapacity() const {
220        return mCapacity;
221    }
222
223private:
224
225    llvm::Value * modByCapacity(IDISA::IDISA_Builder * const b, llvm::Value * const offset) const;
226
227private:
228
229    const size_t    mCapacity;
230    const size_t    mOverflow;
231
232};
233
234class DynamicBuffer final : public StreamSetBuffer {
235
236    friend class KernelBuilder;
237
238    enum Field {BaseAddress, PriorBaseAddress, Capacity};
239
240public:
241    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::DynamicBuffer;}
242
243    DynamicBuffer(const std::unique_ptr<KernelBuilder> & b, llvm::Type * type, size_t initialCapacity, size_t overflowSize = 0, unsigned AddressSpace = 0);
244
245    void allocateBuffer(const std::unique_ptr<KernelBuilder> & b) override;
246
247    void releaseBuffer(const std::unique_ptr<KernelBuilder> & b) const override;
248
249    // void expandBuffer(const std::unique_ptr<KernelBuilder> & b, llvm::Value * consumed, llvm::Value * produced, llvm::Value * required) const;
250
251    llvm::Value * getLinearlyAccessibleItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * fromPosition, llvm::Value * totalItems, llvm::Value * overflowItems = nullptr) const override;
252
253    llvm::Value * getLinearlyWritableItems(const std::unique_ptr<KernelBuilder> & b, llvm::Value * fromPosition, llvm::Value * consumedItems, llvm::Value * overflowItems = nullptr) const override;
254
255    bool hasOverflow() const override {
256        return mOverflow > 0;
257    }
258
259    size_t getOverflowCapacity(const std::unique_ptr<kernel::KernelBuilder> & b) const override;
260
261    size_t getInitialCapacity() const {
262        return mInitialCapacity;
263    }
264
265
266protected:
267
268    llvm::Type * getHandleType(const std::unique_ptr<kernel::KernelBuilder> & b) const override;
269
270    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b) const override;
271
272    void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * addr) const override;
273
274    llvm::Value * getOverflowAddress(IDISA::IDISA_Builder * const b) const override;
275
276    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b) const override;
277
278    void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * capacity) const override;
279
280    llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex) const override;
281
282    llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex) const override;
283
284    llvm::Value * getStreamLogicalBasePtr(IDISA::IDISA_Builder * const b, llvm::Value * const streamIndex, llvm::Value * blockIndex) const override;
285
286    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * absolutePosition) const override;
287
288private:
289
290    llvm::Value * getAllocationSize(IDISA::IDISA_Builder * const b, llvm::Value * const requiredItemCapacity, const size_t overflowSize) const;
291
292    llvm::Value * modByCapacity(IDISA::IDISA_Builder * const b, llvm::Value * const offset) const;
293
294private:
295
296    const size_t    mInitialCapacity;
297    const size_t    mOverflow;
298
299};
300
301using StreamSetBuffers = std::vector<StreamSetBuffer *>;
302using OwnedStreamSetBuffers = std::vector<std::unique_ptr<StreamSetBuffer>>;
303
304}
305#endif // STREAMSET_H
Note: See TracBrowser for help on using the repository browser.