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

Last change on this file since 5998 was 5998, checked in by nmedfort, 12 months ago

Added temporary buffer functionality to the pipeline for single stream source buffers. Fixed memory leak from UCD::UnicodeBreakRE()

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