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

Last change on this file since 5597 was 5597, checked in by nmedfort, 2 years ago

Modified stream set buffers to use heap memory.

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