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

Last change on this file since 5641 was 5641, checked in by cameron, 20 months ago

Modularizing copyBack support

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