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

Last change on this file since 5782 was 5782, checked in by nmedfort, 16 months ago

Initial check-in of LookAhead? support; modified LineBreakKernel? to compute CR+LF using LookAhead?(1) + misc. fixes.

File size: 16.6 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, llvm::Value * consumed, 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
121
122
123protected:
124
125    StreamSetBuffer(BufferKind k, llvm::Type * baseType, llvm::Type * resolvedType, unsigned BufferBlocks, unsigned OverflowBlocks, unsigned AddressSpace);
126
127    virtual llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockNo) const;
128
129    bool isCapacityGuaranteed(const llvm::Value * const index, const size_t capacity) const;
130
131    llvm::Value * modBufferSize(IDISA::IDISA_Builder * const b, llvm::Value * const offset) const;
132
133    virtual llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
134
135    void setProducer(kernel::Kernel * const producer) {
136        assert (producer);
137        mProducer = producer;
138    }
139
140    void addConsumer(kernel::Kernel * const consumer) {
141        assert (consumer);
142        mConsumers.push_back(consumer);
143    }
144
145protected:
146    const BufferKind                 mBufferKind;
147    llvm::Type * const               mType;
148    const size_t                     mBufferBlocks;
149    size_t                           mOverflowBlocks;    /* Number of data blocks of additional space at the end of the buffer for writing only. */
150    const unsigned                   mAddressSpace;
151    llvm::Value *                    mStreamSetBufferPtr;
152    llvm::Type * const               mBaseType;
153    std::string                      mUniqueID;
154    kernel::Kernel *                 mProducer;
155    std::vector<kernel::Kernel *>    mConsumers;
156};   
157
158class SourceBuffer final : public StreamSetBuffer {
159public:
160    static inline bool classof(const StreamSetBuffer * b) {
161        return b->getBufferKind() == BufferKind::SourceBuffer;
162    }
163
164    SourceBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, unsigned MemoryAddressSpace = 0, unsigned StructAddressSpace = 0);
165
166    void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * addr) const override;
167
168    void setBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * size) const override;
169
170    void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * c) const override;
171
172    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
173   
174    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
175   
176    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
177
178    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
179
180    llvm::Type * getStreamSetBlockType() const override;
181
182    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) override;
183
184    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
185
186protected:
187   
188    enum class Field {BaseAddress, BufferedSize, Capacity};
189
190    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
191
192};
193
194class ExternalBuffer final : public StreamSetBuffer {
195public:
196    static inline bool classof(const StreamSetBuffer * b) {
197        return b->getBufferKind() == BufferKind::ExternalBuffer;
198    }
199
200    ExternalBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, llvm::Value * addr, unsigned AddressSpace = 0);
201
202    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
203   
204    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
205
206    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
207
208    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
209
210    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
211};
212
213class CircularBuffer : public StreamSetBuffer {
214public:
215    static inline bool classof(const StreamSetBuffer * b) {
216        return b->getBufferKind() == BufferKind::CircularBuffer;
217    }
218   
219    CircularBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
220
221    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * absolutePosition) const final;
222
223    llvm::Value * getLinearlyCopyableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPos, llvm::Value * avail, bool reverse = false) const final;
224
225protected:
226
227    CircularBuffer(const BufferKind kind, const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace);
228
229    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const final;
230};
231   
232
233//
234//  A CircularCopybackBuffer operates as a circular buffer buffer with an overflow area
235//  for temporary use by the kernel that writes to it.   If the kernel uses the overflow
236//  area, it must perform the doCopyBack action before releasing the buffer for use by
237//  subsequent kernels.
238//  Kernels that read from a CircularCopybackBuffer must not access the overflow area.
239//
240class CircularCopybackBuffer final : public CircularBuffer {
241public:
242    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::CircularCopybackBuffer;}
243   
244    CircularCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace = 0);
245   
246    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
247   
248    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
249
250    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) const override;
251
252};
253   
254class SwizzledCopybackBuffer final : public StreamSetBuffer {
255public:
256    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::SwizzledCopybackBuffer;}
257   
258    SwizzledCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned fieldwidth = 64, unsigned AddressSpace = 0);
259       
260    void createBlockAlignedCopy(IDISA::IDISA_Builder * const b, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * itemsToCopy, const unsigned alignment = 1) const override;
261
262    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
263   
264    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
265
266    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) const override;
267
268protected:
269    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const override;
270private:
271    unsigned mFieldWidth;
272   
273};
274
275// ExpandableBuffers do not allow access to the base stream set but will automatically increase the number of streams
276// within their set whenever the index exceeds its capacity
277//
278class ExpandableBuffer final : public StreamSetBuffer {
279public:
280    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::ExpandableBuffer;}
281
282    ExpandableBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
283
284    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;
285
286    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;
287
288    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
289   
290    llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
291
292    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
293
294    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
295
296protected:
297
298    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
299
300    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * blockIndex, llvm::Value *) const override;
301
302private:
303
304    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;
305
306private:
307
308    const uint64_t  mInitialCapacity;
309
310};
311   
312// Dynamically allocated circular buffers: TODO: add copyback, swizzle support, dynamic allocation, producer, consumer, length
313class DynamicBuffer: public StreamSetBuffer {
314public:
315    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::DynamicBuffer;}
316   
317    DynamicBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t initialCapacity, size_t overflowBlocks = 0, unsigned swizzleFactor = 1, unsigned addrSpace = 0);
318   
319    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
320   
321    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
322   
323    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
324
325    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
326
327    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * absolutePosition) const override;
328   
329    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
330   
331    void doubleCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle);
332
333    void genCopyBackLogic(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * priorProduced, llvm::Value * newProduced, const std::string) const override;
334
335protected:
336    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
337   
338    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const override;
339
340   
341private:
342    /* Static data */
343    llvm::Type * mBufferStructType;      /* The type of the buffer struct. */
344    unsigned   mSwizzleFactor;     /* Number of streams swizzled together per block.  Must be a small power of 2. Default: 1. */
345   
346    /* Dynamic data fields stored in the buffer struct */
347   
348    enum class Field {BaseAddress, PriorBaseAddress, AllocatedCapacity, WorkingBlocks, Length, ProducedPosition, ConsumedPosition, FieldCount};
349   
350    /* BaseAddress - the physical base address of the memory area for stream set data.
351     PriorBaseAddress - the physical base address of the previous memory area for stream set data
352     (the immediately prior memory area is preserved in case any users in other threads
353     are accessing it).
354     WorkingBlocks - the physical size of the buffer for use in reading and writing data.
355     AllocatedCapacity - physical size available for expansion in place
356     Length - actual final length of stream set or -1 for unknown
357     ProducedPosition - the total number of items ever generated and stored in the buffer
358     ConsumedPosition - the number of buffer items that are known to have been fully processed by all users
359     */
360   
361};
362
363
364}
365#endif // STREAMSET_H
Note: See TracBrowser for help on using the repository browser.