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

Last change on this file since 5699 was 5650, checked in by cameron, 22 months ago

Multiblock kernel builder support for ExternalBuffer? inputs; clean-up

File size: 16.5 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
10namespace IDISA { class IDISA_Builder; }
11namespace llvm { class Value; }
12namespace kernel { class Kernel; }
13namespace kernel { class KernelBuilder; }
14
15namespace parabix {
16   
17class StreamSetBuffer {
18    friend class kernel::Kernel;
19    friend class kernel::KernelBuilder;
20public:
21
22    enum class BufferKind : unsigned {
23        SourceBuffer
24        , ExternalBuffer
25        , CircularBuffer
26        , CircularCopybackBuffer
27        , SwizzledCopybackBuffer
28        , ExpandableBuffer
29        , DynamicBuffer
30    };
31
32    BufferKind getBufferKind() const {
33        return mBufferKind;
34    }
35   
36    std::string getUniqueID() const {
37        return mUniqueID;
38    }
39
40    llvm::Type * getType() const {
41        return mType;
42    }
43   
44    llvm::Type * getBaseType() const {
45        return mBaseType;
46    }
47
48    llvm::PointerType * getPointerType() const {
49        return getType()->getPointerTo(mAddressSpace);
50    }
51
52    size_t getBufferBlocks() const {
53        return mBufferBlocks;
54    }
55
56    llvm::Value * getStreamSetHandle() const {
57        return mStreamSetBufferPtr;
58    }
59   
60    virtual llvm::Type * getStreamSetBlockType() const;
61   
62    virtual void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb);
63
64    virtual void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const;
65
66    virtual llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const;
67
68    virtual llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex, const bool readOnly) const;
69   
70    virtual llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
71
72    virtual llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * absolutePosition) const;
73
74    virtual void setBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * addr, llvm::Value *) const;
75
76    virtual void setBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * size, llvm::Value *) const;
77   
78    virtual llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
79   
80    virtual void setCapacity(IDISA::IDISA_Builder * const iBuilder, llvm::Value * size, llvm::Value *) const;
81   
82    virtual llvm::Value * getCapacity(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
83   
84    // The number of items that cam be linearly accessed from a given logical stream position.
85    virtual llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPos, llvm::Value * avail, bool reverse = false) const;
86   
87    void createBlockCopy(IDISA::IDISA_Builder * const iBuilder, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * blocksToCopy) const;
88
89    virtual void createBlockAlignedCopy(IDISA::IDISA_Builder * const iBuilder, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * itemsToCopy) const;
90
91    virtual llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, bool reverse = false) const;
92   
93    virtual bool supportsCopyBack() const {
94        return false;  // Overridden to return true by buffer types that support copyback.
95    }
96    virtual void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string);
97   
98    virtual ~StreamSetBuffer() = 0;
99
100    kernel::Kernel * getProducer() const {
101        return mProducer;
102    }
103
104    const std::vector<kernel::Kernel *> & getConsumers() const {
105        return mConsumers;
106    }
107
108protected:
109
110    StreamSetBuffer(BufferKind k, llvm::Type * baseType, llvm::Type * resolvedType, unsigned BufferBlocks, unsigned AddressSpace);
111
112    // Get the buffer pointer for a given block of the stream set.
113    virtual llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockNo) const = 0;
114
115    bool isCapacityGuaranteed(const llvm::Value * const index, const size_t capacity) const;
116
117    llvm::Value * modByBufferBlocks(IDISA::IDISA_Builder * const iBuilder, llvm::Value * const offset) const;
118
119    virtual llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
120
121    void setProducer(kernel::Kernel * const producer) {
122        assert (producer);
123        mProducer = producer;
124    }
125
126    void addConsumer(kernel::Kernel * const consumer) {
127        assert (consumer);
128        mConsumers.push_back(consumer);
129    }
130
131protected:
132    const BufferKind                 mBufferKind;
133    llvm::Type * const               mType;
134    const size_t                     mBufferBlocks;
135    const unsigned                   mAddressSpace;
136    llvm::Value *                    mStreamSetBufferPtr;
137    llvm::Type * const               mBaseType;
138    std::string                      mUniqueID;
139    kernel::Kernel *                 mProducer;
140    std::vector<kernel::Kernel *>    mConsumers;
141};   
142
143class SourceBuffer final : public StreamSetBuffer {
144public:
145    static inline bool classof(const StreamSetBuffer * b) {
146        return b->getBufferKind() == BufferKind::SourceBuffer;
147    }
148
149    SourceBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, unsigned MemoryAddressSpace = 0, unsigned StructAddressSpace = 0);
150
151    void setBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * addr) const override;
152
153    void setBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * size) const override;
154
155    void setCapacity(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * c) const override;
156
157    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
158   
159    llvm::Value * getCapacity(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
160   
161    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
162
163    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, bool reverse = false) const override;
164
165    llvm::Type * getStreamSetBlockType() const override;
166
167    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) override;
168
169    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
170
171protected:
172   
173    enum class Field {BaseAddress, BufferedSize, Capacity};
174
175    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
176
177    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockNo) const override;
178
179};
180
181class ExternalBuffer final : public StreamSetBuffer {
182public:
183    static inline bool classof(const StreamSetBuffer * b) {
184        return b->getBufferKind() == BufferKind::ExternalBuffer;
185    }
186
187    ExternalBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, llvm::Value * addr, unsigned AddressSpace = 0);
188
189    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
190   
191    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
192
193    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
194
195protected:
196    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockNo) const override;
197};
198
199class CircularBuffer : public StreamSetBuffer {
200public:
201    static inline bool classof(const StreamSetBuffer * b) {
202        return b->getBufferKind() == BufferKind::CircularBuffer;
203    }
204   
205    CircularBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
206
207    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * absolutePosition) const final;
208
209protected:
210
211    CircularBuffer(const BufferKind kind, const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
212
213    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockIndex) const final;
214};
215   
216
217//
218//  A CircularCopybackBuffer operates as a circular buffer buffer with an overflow area
219//  for temporary use by the kernel that writes to it.   If the kernel uses the overflow
220//  area, it must perform the doCopyBack action before releasing the buffer for use by
221//  subsequent kernels.
222//  Kernels that read from a CircularCopybackBuffer must not access the overflow area.
223//
224class CircularCopybackBuffer final : public CircularBuffer {
225public:
226    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::CircularCopybackBuffer;}
227   
228    CircularCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace = 0);
229   
230    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, bool reverse = false) const override;
231   
232    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
233
234    bool supportsCopyBack() const override {
235        return mOverflowBlocks > 0; 
236    }
237   
238    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) override;
239   
240   
241private:
242    size_t mOverflowBlocks;
243
244};
245   
246class SwizzledCopybackBuffer final : public StreamSetBuffer {
247public:
248    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::SwizzledCopybackBuffer;}
249   
250    SwizzledCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned fieldwidth = 64, unsigned AddressSpace = 0);
251       
252    void createBlockAlignedCopy(IDISA::IDISA_Builder * const iBuilder, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * itemsToCopy) const override;
253
254    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, bool reverse = false) const override;
255   
256    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
257
258    bool supportsCopyBack() const override {
259        return mOverflowBlocks > 0; 
260    }
261   
262    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) override;
263
264protected:
265    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockIndex) const override;
266private:
267    size_t mOverflowBlocks;
268    unsigned mFieldWidth;
269   
270};
271
272// ExpandableBuffers do not allow access to the base stream set but will automatically increase the number of streams
273// within their set whenever the index exceeds its capacity
274//
275class ExpandableBuffer final : public StreamSetBuffer {
276public:
277    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::ExpandableBuffer;}
278
279    ExpandableBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
280
281    llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const override;
282
283    llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex, const bool readOnly) const override;
284
285    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
286   
287    llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
288
289    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
290
291    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
292
293protected:
294
295    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
296
297    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * blockIndex, llvm::Value *) const override;
298
299private:
300
301    std::pair<llvm::Value *, llvm::Value *> getInternalStreamBuffer(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const;
302
303private:
304
305    const uint64_t  mInitialCapacity;
306
307};
308   
309// Dynamically allocated circular buffers: TODO: add copyback, swizzle support, dynamic allocation, producer, consumer, length
310class DynamicBuffer: public StreamSetBuffer {
311public:
312    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::DynamicBuffer;}
313   
314    DynamicBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t initialCapacity, size_t overflowBlocks = 0, unsigned swizzleFactor = 1, unsigned addrSpace = 0);
315   
316    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
317   
318    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromPosition, bool reverse = false) const override;
319   
320    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
321
322    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
323
324    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * streamIndex, llvm::Value * absolutePosition) const override;
325   
326    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
327   
328    void doubleCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle);
329
330    bool supportsCopyBack() const override {
331        return mOverflowBlocks > 0; 
332    }
333       
334    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) override;
335
336protected:
337    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
338   
339    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const override;
340
341   
342private:
343    /* Static data */
344    llvm::Type * mBufferStructType;      /* The type of the buffer struct. */
345    unsigned   mSwizzleFactor;     /* Number of streams swizzled together per block.  Must be a small power of 2. Default: 1. */
346    size_t     mOverflowBlocks;    /* Number of data blocks of additional space at the end of the buffer for writing only. */
347   
348    /* Dynamic data fields stored in the buffer struct */
349   
350    enum class Field {BaseAddress, PriorBaseAddress, AllocatedCapacity, WorkingBlocks, Length, ProducedPosition, ConsumedPosition, FieldCount};
351   
352    /* BaseAddress - the physical base address of the memory area for stream set data.
353     PriorBaseAddress - the physical base address of the previous memory area for stream set data
354     (the immediately prior memory area is preserved in case any users in other threads
355     are accessing it).
356     WorkingBlocks - the physical size of the buffer for use in reading and writing data.
357     AllocatedCapacity - physical size available for expansion in place
358     Length - actual final length of stream set or -1 for unknown
359     ProducedPosition - the total number of items ever generated and stored in the buffer
360     ConsumedPosition - the number of buffer items that are known to have been fully processed by all users
361     */
362   
363};
364
365
366}
367#endif // STREAMSET_H
Note: See TracBrowser for help on using the repository browser.