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

Last change on this file since 5452 was 5452, checked in by cameron, 2 years ago

Fix some issues with MultiBlockKernel? builder

File size: 12.3 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        BlockBuffer
24        , SourceBuffer
25        , ExternalBuffer
26        , CircularBuffer
27        , CircularCopybackBuffer
28        , SwizzledCopybackBuffer
29        , ExpandableBuffer
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 * getStreamSetBasePtr() const {
57        return mStreamSetBufferPtr;
58    }
59
60    virtual void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder);
61
62    virtual void releaseBuffer(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
63
64    virtual llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const;
65
66    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;
67   
68    virtual llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
69
70    virtual llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * absolutePosition) const;
71
72    virtual void setBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * addr, llvm::Value *) const;
73
74    virtual void setBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * size, llvm::Value *) const;
75
76    virtual llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
77
78    // The number of items that cam be linearly accessed from a given logical stream position.
79    virtual llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromPosition) const;
80   
81    virtual llvm::Value * getLinearlyAccessibleBlocks(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromBlock) const;
82   
83    virtual void createBlockAlignedCopy(IDISA::IDISA_Builder * const iBuilder, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * itemsToCopy) const;
84
85    virtual llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromPosition) const;
86   
87    virtual llvm::Value * getLinearlyWritableBlocks(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromBlock) const;
88   
89    virtual ~StreamSetBuffer() = 0;
90
91    kernel::Kernel * getProducer() const {
92        return mProducer;
93    }
94
95    const std::vector<kernel::Kernel *> & getConsumers() const {
96        return mConsumers;
97    }
98
99protected:
100
101    StreamSetBuffer(BufferKind k, llvm::Type * baseType, llvm::Type * resolvedType, unsigned BufferBlocks, unsigned AddressSpace);
102
103    // Get the buffer pointer for a given block of the stream set.
104    virtual llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockNo) const = 0;
105
106    bool isCapacityGuaranteed(const llvm::Value * const index, const size_t capacity) const;
107
108    llvm::Value * modByBufferBlocks(IDISA::IDISA_Builder * const iBuilder, llvm::Value * const offset) const;
109
110    virtual llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const;
111
112    void setProducer(kernel::Kernel * const producer) {
113        assert (producer);
114        mProducer = producer;
115    }
116
117    void addConsumer(kernel::Kernel * const consumer) {
118        assert (consumer);
119        mConsumers.push_back(consumer);
120    }
121
122protected:
123    const BufferKind                 mBufferKind;
124    llvm::Type * const               mType;
125    const size_t                     mBufferBlocks;
126    const unsigned                   mAddressSpace;
127    llvm::Value *                    mStreamSetBufferPtr;
128    llvm::Type * const               mBaseType;
129    std::string                      mUniqueID;
130    kernel::Kernel *                 mProducer;
131    std::vector<kernel::Kernel *>    mConsumers;
132};   
133
134class SingleBlockBuffer final : public StreamSetBuffer {
135public:
136    static inline bool classof(const StreamSetBuffer * b) {
137        return b->getBufferKind() == BufferKind::BlockBuffer;
138    }   
139
140    SingleBlockBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type);
141
142protected:
143
144    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockNo) const override;
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    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
160
161    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromPosition) const override;
162
163protected:
164
165    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
166
167    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockNo) const override;
168
169};
170
171class ExternalBuffer final : public StreamSetBuffer {
172public:
173    static inline bool classof(const StreamSetBuffer * b) {
174        return b->getBufferKind() == BufferKind::ExternalBuffer;
175    }
176
177    ExternalBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, llvm::Value * addr, unsigned AddressSpace = 0);
178
179    // Can't allocate - raise an error. */
180    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
181
182    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromPosition) const override;
183
184protected:
185    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockNo) const override;
186};
187
188class CircularBuffer : public StreamSetBuffer {
189public:
190    static inline bool classof(const StreamSetBuffer * b) {
191        return b->getBufferKind() == BufferKind::CircularBuffer;
192    }
193   
194    CircularBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
195
196    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * absolutePosition) const final;
197
198protected:
199
200    CircularBuffer(const BufferKind kind, const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
201
202    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockIndex) const final;
203};
204   
205
206//
207//  A CircularCopybackBuffer operates as a circular buffer buffer with an overflow area
208//  for temporary use by the kernel that writes to it.   If the kernel uses the overflow
209//  area, it must perform the doCopyBack action before releasing the buffer for use by
210//  subsequent kernels.
211//  Kernels that read from a CircularCopybackBuffer must not access the overflow area.
212//
213class CircularCopybackBuffer final : public CircularBuffer {
214public:
215    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::CircularCopybackBuffer;}
216   
217    CircularCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace = 0);
218
219    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
220   
221    // Generate copyback code for the given number of overflowItems.
222    void createCopyBack(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * overflowItems) const;
223       
224    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromPosition) const override;
225   
226    llvm::Value * getLinearlyWritableBlocks(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromBlock) const override;
227   
228private:
229    size_t mOverflowBlocks;
230
231};
232   
233class SwizzledCopybackBuffer final : public StreamSetBuffer {
234public:
235    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::SwizzledCopybackBuffer;}
236   
237    SwizzledCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned fieldwidth = 64, unsigned AddressSpace = 0);
238   
239    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
240   
241    void createBlockAlignedCopy(IDISA::IDISA_Builder * const iBuilder, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * itemsToCopy) const override;
242
243    // Generate copyback code for the given number of overflowItems.
244    void createCopyBack(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * overflowItems) const;
245   
246    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromPosition) const override;
247   
248    llvm::Value * getLinearlyWritableBlocks(IDISA::IDISA_Builder * constiBuilder, llvm::Value * fromBlock) const override;
249   
250protected:
251    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * blockIndex) const override;
252private:
253    size_t mOverflowBlocks;
254    unsigned mFieldWidth;
255   
256};
257
258// ExpandableBuffers do not allow access to the base stream set but will automatically increase the number of streams
259// within their set whenever the index exceeds its capacity
260//
261class ExpandableBuffer final : public StreamSetBuffer {
262public:
263    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::ExpandableBuffer;}
264
265    ExpandableBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
266
267    llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const override;
268
269    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;
270
271    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const iBuilder, llvm::Value * fromPosition) const override;
272
273    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) override;
274
275    llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
276
277    void releaseBuffer(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
278
279protected:
280
281    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self) const override;
282
283    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const iBuilder, llvm::Value * blockIndex, llvm::Value *) const override;
284
285private:
286
287    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;
288
289private:
290
291    const uint64_t  mInitialCapacity;
292
293};
294
295}
296#endif // STREAMSET_H
Note: See TracBrowser for help on using the repository browser.