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

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

:getStreamSetBlockType

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