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

Last change on this file since 5755 was 5755, checked in by nmedfort, 18 months ago

Bug fixes and simplified MultiBlockKernel? logic

File size: 16.3 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    unsigned getAddressSpace() const {
49        return mAddressSpace;
50    }
51
52    llvm::PointerType * getPointerType() const {
53        return getType()->getPointerTo(getAddressSpace());
54    }
55
56    size_t getBufferBlocks() const {
57        return mBufferBlocks;
58    }
59
60    llvm::Value * getStreamSetHandle() const {
61        return mStreamSetBufferPtr;
62    }
63   
64    virtual llvm::Type * getStreamSetBlockType() const;
65   
66    virtual void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb);
67
68    virtual void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const;
69
70    virtual llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * addr, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const;
71
72    virtual llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * addr, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex, const bool readOnly) const;
73   
74    virtual llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
75
76    virtual llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * absolutePosition) const;
77
78    virtual void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * addr, llvm::Value *) const;
79
80    virtual void setBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * size, llvm::Value *) const;
81   
82    virtual llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
83   
84    virtual void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * size, llvm::Value *) const;
85   
86    virtual llvm::Value * getCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
87   
88    // The number of items that cam be linearly accessed from a given logical stream position.
89    virtual llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPos, llvm::Value * avail, bool reverse = false) const;
90
91    virtual llvm::Value * getLinearlyCopyableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPos, llvm::Value * avail, bool reverse = false) const {
92        return getLinearlyAccessibleItems(b, handle, fromPos, avail, reverse);
93    }
94   
95    void createBlockCopy(IDISA::IDISA_Builder * const b, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * blocksToCopy) const;
96
97    virtual void createBlockAlignedCopy(IDISA::IDISA_Builder * const b, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * itemsToCopy, const unsigned alignment = 1) const;
98
99    virtual llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, bool reverse = false) const;
100   
101    bool supportsCopyBack() const {
102        return mOverflowBlocks != 0;
103    }
104
105    size_t overflowSize() const {
106        return mOverflowBlocks;
107    }
108
109    virtual void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) const;
110   
111    virtual ~StreamSetBuffer() = 0;
112
113    kernel::Kernel * getProducer() const {
114        return mProducer;
115    }
116
117    const std::vector<kernel::Kernel *> & getConsumers() const {
118        return mConsumers;
119    }
120
121protected:
122
123    StreamSetBuffer(BufferKind k, llvm::Type * baseType, llvm::Type * resolvedType, unsigned BufferBlocks, unsigned OverflowBlocks, unsigned AddressSpace);
124
125    virtual llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockNo) const;
126
127    bool isCapacityGuaranteed(const llvm::Value * const index, const size_t capacity) const;
128
129    llvm::Value * modBufferSize(IDISA::IDISA_Builder * const b, llvm::Value * const offset) const;
130
131    virtual llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
132
133    void setProducer(kernel::Kernel * const producer) {
134        assert (producer);
135        mProducer = producer;
136    }
137
138    void addConsumer(kernel::Kernel * const consumer) {
139        assert (consumer);
140        mConsumers.push_back(consumer);
141    }
142
143protected:
144    const BufferKind                 mBufferKind;
145    llvm::Type * const               mType;
146    const size_t                     mBufferBlocks;
147    size_t                           mOverflowBlocks;    /* Number of data blocks of additional space at the end of the buffer for writing only. */
148    const unsigned                   mAddressSpace;
149    llvm::Value *                    mStreamSetBufferPtr;
150    llvm::Type * const               mBaseType;
151    std::string                      mUniqueID;
152    kernel::Kernel *                 mProducer;
153    std::vector<kernel::Kernel *>    mConsumers;
154};   
155
156class SourceBuffer final : public StreamSetBuffer {
157public:
158    static inline bool classof(const StreamSetBuffer * b) {
159        return b->getBufferKind() == BufferKind::SourceBuffer;
160    }
161
162    SourceBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, unsigned MemoryAddressSpace = 0, unsigned StructAddressSpace = 0);
163
164    void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * addr) const override;
165
166    void setBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * size) const override;
167
168    void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * c) const override;
169
170    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
171   
172    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
173   
174    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
175
176    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, bool reverse = false) const override;
177
178    llvm::Type * getStreamSetBlockType() const override;
179
180    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) override;
181
182    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
183
184protected:
185   
186    enum class Field {BaseAddress, BufferedSize, Capacity};
187
188    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
189
190};
191
192class ExternalBuffer final : public StreamSetBuffer {
193public:
194    static inline bool classof(const StreamSetBuffer * b) {
195        return b->getBufferKind() == BufferKind::ExternalBuffer;
196    }
197
198    ExternalBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, llvm::Value * addr, unsigned AddressSpace = 0);
199
200    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
201   
202    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, bool reverse = false) const override;
203
204    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
205
206    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
207
208};
209
210class CircularBuffer : public StreamSetBuffer {
211public:
212    static inline bool classof(const StreamSetBuffer * b) {
213        return b->getBufferKind() == BufferKind::CircularBuffer;
214    }
215   
216    CircularBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
217
218    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * absolutePosition) const final;
219
220    llvm::Value * getLinearlyCopyableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPos, llvm::Value * avail, bool reverse = false) const final;
221
222protected:
223
224    CircularBuffer(const BufferKind kind, const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace);
225
226    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const final;
227};
228   
229
230//
231//  A CircularCopybackBuffer operates as a circular buffer buffer with an overflow area
232//  for temporary use by the kernel that writes to it.   If the kernel uses the overflow
233//  area, it must perform the doCopyBack action before releasing the buffer for use by
234//  subsequent kernels.
235//  Kernels that read from a CircularCopybackBuffer must not access the overflow area.
236//
237class CircularCopybackBuffer final : public CircularBuffer {
238public:
239    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::CircularCopybackBuffer;}
240   
241    CircularCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace = 0);
242   
243    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, bool reverse = false) const override;
244   
245    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
246
247    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) const override;
248
249};
250   
251class SwizzledCopybackBuffer final : public StreamSetBuffer {
252public:
253    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::SwizzledCopybackBuffer;}
254   
255    SwizzledCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned fieldwidth = 64, unsigned AddressSpace = 0);
256       
257    void createBlockAlignedCopy(IDISA::IDISA_Builder * const b, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * itemsToCopy, const unsigned alignment = 1) const override;
258
259    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, bool reverse = false) const override;
260   
261    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
262
263    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) const override;
264
265protected:
266    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const override;
267private:
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 b, llvm::Value * handle, llvm::Value * addr, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const override;
282
283    llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * addr, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex, const bool readOnly) const override;
284
285    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
286   
287    llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
288
289    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) 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 b, llvm::Value * handle) const override;
296
297    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * blockIndex, llvm::Value *) const override;
298
299private:
300
301    std::pair<llvm::Value *, llvm::Value *> getInternalStreamBuffer(IDISA::IDISA_Builder * const b, llvm::Value * handle, 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 b, llvm::Value * handle, 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 * absolutePosition) const override;
325   
326    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
327   
328    void doubleCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle);
329
330    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) const override;
331
332protected:
333    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
334   
335    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const override;
336
337   
338private:
339    /* Static data */
340    llvm::Type * mBufferStructType;      /* The type of the buffer struct. */
341    unsigned   mSwizzleFactor;     /* Number of streams swizzled together per block.  Must be a small power of 2. Default: 1. */
342   
343    /* Dynamic data fields stored in the buffer struct */
344   
345    enum class Field {BaseAddress, PriorBaseAddress, AllocatedCapacity, WorkingBlocks, Length, ProducedPosition, ConsumedPosition, FieldCount};
346   
347    /* BaseAddress - the physical base address of the memory area for stream set data.
348     PriorBaseAddress - the physical base address of the previous memory area for stream set data
349     (the immediately prior memory area is preserved in case any users in other threads
350     are accessing it).
351     WorkingBlocks - the physical size of the buffer for use in reading and writing data.
352     AllocatedCapacity - physical size available for expansion in place
353     Length - actual final length of stream set or -1 for unknown
354     ProducedPosition - the total number of items ever generated and stored in the buffer
355     ConsumedPosition - the number of buffer items that are known to have been fully processed by all users
356     */
357   
358};
359
360
361}
362#endif // STREAMSET_H
Note: See TracBrowser for help on using the repository browser.