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

Last change on this file since 5501 was 5501, checked in by cameron, 22 months ago

setCapacity/getCapacity/getLinearlyAvailableItems for SourceBuffer?

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