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

Last change on this file since 5933 was 5933, checked in by cameron, 13 months ago

Including IR/DerivedTypes.h for missing inlines: getSequentialElementType

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