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

Last change on this file since 6004 was 5998, checked in by nmedfort, 18 months ago

Added temporary buffer functionality to the pipeline for single stream source buffers. Fixed memory leak from UCD::UnicodeBreakRE()

File size: 14.8 KB
RevLine 
[5044]1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
[4986]6#ifndef STREAMSET_H
7#define STREAMSET_H
8
[5260]9#include <llvm/IR/Type.h>  // for Type
[5933]10#include <llvm/IR/DerivedTypes.h>  // for Type
[5260]11namespace IDISA { class IDISA_Builder; }
12namespace llvm { class Value; }
[5435]13namespace kernel { class Kernel; }
[5260]14namespace kernel { class KernelBuilder; }
[5191]15
[5100]16namespace parabix {
17   
[5044]18class StreamSetBuffer {
[5435]19    friend class kernel::Kernel;
[5260]20    friend class kernel::KernelBuilder;
[5044]21public:
[5202]22
[5398]23    enum class BufferKind : unsigned {
[5457]24        SourceBuffer
[5429]25        , ExternalBuffer
[5398]26        , CircularBuffer
27        , CircularCopybackBuffer
28        , ExpandableBuffer
[5541]29        , DynamicBuffer
[5398]30    };
[5202]31
[5297]32    BufferKind getBufferKind() const {
[5217]33        return mBufferKind;
34    }
[5395]35   
36    std::string getUniqueID() const {
37        return mUniqueID;
38    }
[5133]39
[5297]40    llvm::Type * getType() const {
[5307]41        return mType;
[5217]42    }
[5506]43   
[5297]44    llvm::Type * getBaseType() const {
[5307]45        return mBaseType;
[5217]46    }
[4986]47
[5843]48    // Return the number of streams for a static stream set or 0 for an expandable stream set.
49    unsigned getNumOfStreams () const {
50        if (mBufferKind == BufferKind::ExpandableBuffer) return 0;
51        size_t numStreams = 1;
52        if (mBaseType->isArrayTy()) {
53            numStreams = mBaseType->getArrayNumElements();
54        }
55        return numStreams;
56    }
57   
58    unsigned getStreamFieldWidth () const {
59        if (mBaseType->isArrayTy()) {
60            return mBaseType->getArrayElementType()->getScalarSizeInBits();
61        }
62        return mBaseType->getScalarSizeInBits();
63    }
64   
[5755]65    unsigned getAddressSpace() const {
66        return mAddressSpace;
67    }
68
[5297]69    llvm::PointerType * getPointerType() const {
[5755]70        return getType()->getPointerTo(getAddressSpace());
[5297]71    }
[5260]72
[5301]73    size_t getBufferBlocks() const {
74        return mBufferBlocks;
[5297]75    }
[5260]76
[5542]77    llvm::Value * getStreamSetHandle() const {
[5297]78        return mStreamSetBufferPtr;
79    }
[5998]80
81    bool supportsCopyBack() const {
82        return mOverflowBlocks != 0;
83    }
84
85    virtual bool isUnbounded() const {
86        return false;
87    }
88
89    size_t overflowSize() const {
90        return mOverflowBlocks;
91    }
92
93    virtual ~StreamSetBuffer() = 0;
94
95    kernel::Kernel * getProducer() const {
96        return mProducer;
97    }
98
99    const std::vector<kernel::Kernel *> & getConsumers() const {
100        return mConsumers;
101    }
102
[5544]103    virtual void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb);
[5217]104
[5544]105    virtual void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const;
[5386]106
[5998]107    llvm::PointerType * getStreamSetPointerType() const {
108        return getStreamSetBlockType()->getPointerTo(mAddressSpace);
109    }
110
111protected:
112
113    virtual llvm::Type * getStreamSetBlockType() const;
114
[5985]115    virtual llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const;
[5260]116
[5985]117    virtual llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex, const bool readOnly) const;
[5044]118   
[5755]119    virtual llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
[5329]120
[5755]121    virtual llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * absolutePosition) const;
[5135]122
[5998]123    virtual void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * addr) const;
[5398]124
[5998]125    virtual void setBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * size) const;
[5501]126   
[5755]127    virtual llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
[5501]128   
[5755]129    virtual void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * size, llvm::Value *) const;
[5501]130   
[5755]131    virtual llvm::Value * getCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
[5501]132   
[5301]133    // The number of items that cam be linearly accessed from a given logical stream position.
[5755]134    virtual llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPos, llvm::Value * avail, bool reverse = false) const;
135
136    void createBlockCopy(IDISA::IDISA_Builder * const b, llvm::Value * targetBlockPtr, llvm::Value * sourceBlockPtr, llvm::Value * blocksToCopy) const;
[5706]137
[5782]138    virtual llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const;
[5434]139   
[5856]140    virtual void doubleCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
141
[5755]142    StreamSetBuffer(BufferKind k, llvm::Type * baseType, llvm::Type * resolvedType, unsigned BufferBlocks, unsigned OverflowBlocks, unsigned AddressSpace);
[5260]143
[5353]144    bool isCapacityGuaranteed(const llvm::Value * const index, const size_t capacity) const;
145
[5755]146    llvm::Value * modBufferSize(IDISA::IDISA_Builder * const b, llvm::Value * const offset) const;
[5353]147
[5755]148    virtual llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
[5377]149
[5985]150    virtual llvm::Value * getOverflowAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const;
151
[5435]152    void setProducer(kernel::Kernel * const producer) {
[5408]153        assert (producer);
154        mProducer = producer;
155    }
156
[5435]157    void addConsumer(kernel::Kernel * const consumer) {
[5408]158        assert (consumer);
159        mConsumers.push_back(consumer);
160    }
161
[5202]162protected:
[5436]163    const BufferKind                 mBufferKind;
164    llvm::Type * const               mType;
165    const size_t                     mBufferBlocks;
[5755]166    size_t                           mOverflowBlocks;    /* Number of data blocks of additional space at the end of the buffer for writing only. */
[5436]167    const unsigned                   mAddressSpace;
168    llvm::Value *                    mStreamSetBufferPtr;
169    llvm::Type * const               mBaseType;
170    std::string                      mUniqueID;
[5435]171    kernel::Kernel *                 mProducer;
172    std::vector<kernel::Kernel *>    mConsumers;
[5100]173};   
[4986]174
[5429]175class SourceBuffer final : public StreamSetBuffer {
[5998]176    friend class kernel::KernelBuilder;
[5100]177public:
[5202]178    static inline bool classof(const StreamSetBuffer * b) {
[5429]179        return b->getBufferKind() == BufferKind::SourceBuffer;
[5202]180    }
[5398]181
[5440]182    SourceBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, unsigned MemoryAddressSpace = 0, unsigned StructAddressSpace = 0);
[5123]183
[5985]184    bool isUnbounded() const override {
185        return true;
186    }
187
[5998]188protected:
189
[5755]190    void setBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * addr) const override;
[5398]191
[5755]192    void setBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * size) const override;
[5398]193
[5755]194    void setCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * c) const override;
[5501]195
[5755]196    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5501]197   
[5755]198    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5501]199   
[5755]200    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
[5706]201
[5782]202    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
[5398]203
[5597]204    llvm::Type * getStreamSetBlockType() const override;
[5503]205
[5597]206    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) override;
207
208    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
209
[5985]210    enum Field {BaseAddress, BufferedSize, Capacity};
[5398]211
[5755]212    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5398]213
214};
215
[5429]216class ExternalBuffer final : public StreamSetBuffer {
[5998]217    friend class kernel::KernelBuilder;
[5377]218public:
219    static inline bool classof(const StreamSetBuffer * b) {
[5429]220        return b->getBufferKind() == BufferKind::ExternalBuffer;
[5377]221    }
222
[5436]223    ExternalBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, llvm::Value * addr, unsigned AddressSpace = 0);
[5377]224
[5985]225    bool isUnbounded() const override {
226        return true;
227    }
228
[5998]229    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
230
231    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
232
233protected:
234
[5755]235    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
[5650]236   
[5782]237    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
[5706]238
[5985]239    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
240
[5757]241    llvm::Value * getCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5429]242};
[5377]243
[5446]244class CircularBuffer : public StreamSetBuffer {
[5998]245    friend class kernel::KernelBuilder;
[5100]246public:
[5202]247    static inline bool classof(const StreamSetBuffer * b) {
248        return b->getBufferKind() == BufferKind::CircularBuffer;
249    }
[5301]250   
[5436]251    CircularBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
[5217]252
[5998]253protected:
254
[5755]255    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * absolutePosition) const final;
[5446]256
[5755]257    CircularBuffer(const BufferKind kind, const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace);
[5446]258
[5100]259};
[5185]260   
[5301]261
[5185]262//
[5301]263//  A CircularCopybackBuffer operates as a circular buffer buffer with an overflow area
264//  for temporary use by the kernel that writes to it.   If the kernel uses the overflow
265//  area, it must perform the doCopyBack action before releasing the buffer for use by
266//  subsequent kernels.
267//  Kernels that read from a CircularCopybackBuffer must not access the overflow area.
268//
[5446]269class CircularCopybackBuffer final : public CircularBuffer {
[5998]270    friend class kernel::KernelBuilder;
[5185]271public:
[5301]272    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::CircularCopybackBuffer;}
[5185]273   
[5985]274    CircularCopybackBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks = 1, unsigned AddressSpace = 0);
[5793]275       
[5185]276};
[5432]277
[5260]278// ExpandableBuffers do not allow access to the base stream set but will automatically increase the number of streams
279// within their set whenever the index exceeds its capacity
280//
[5377]281class ExpandableBuffer final : public StreamSetBuffer {
[5998]282    friend class kernel::KernelBuilder;
[5260]283public:
284    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::ExpandableBuffer;}
285
[5436]286    ExpandableBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace = 0);
[5260]287
[5998]288    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
289
290    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & kb) const override;
291
292protected:
293
[5985]294    llvm::Value * getStreamBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const override;
[5260]295
[5985]296    llvm::Value * getStreamPackPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * streamIndex, llvm::Value * blockIndex, llvm::Value * packIndex, const bool readOnly) const override;
[5260]297
[5755]298    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
[5650]299   
[5755]300    llvm::Value * getStreamSetCount(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5597]301
[5755]302    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5377]303
[5320]304private:
305
[5755]306    std::pair<llvm::Value *, llvm::Value *> getInternalStreamBuffer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * streamIndex, llvm::Value * blockIndex, const bool readOnly) const;
[5340]307
[5320]308private:
309
310    const uint64_t  mInitialCapacity;
311
[5260]312};
[5541]313   
314// Dynamically allocated circular buffers: TODO: add copyback, swizzle support, dynamic allocation, producer, consumer, length
[5856]315class DynamicBuffer final : public StreamSetBuffer {
[5998]316
317    friend class kernel::KernelBuilder;
318
[5985]319    /* Dynamic data fields stored in the buffer struct */
320    enum Field {BaseAddress, PriorBaseAddress, AllocatedCapacity, WorkingBlocks, Length, ProducedPosition, ConsumedPosition, FieldCount};
321
322    /* BaseAddress - the physical base address of the memory area for stream set data.
323     PriorBaseAddress - the physical base address of the previous memory area for stream set data
324     (the immediately prior memory area is preserved in case any users in other threads
325     are accessing it).
326     WorkingBlocks - the physical size of the buffer for use in reading and writing data.
327     AllocatedCapacity - physical size available for expansion in place
328     Length - actual final length of stream set or -1 for unknown
329     ProducedPosition - the total number of items ever generated and stored in the buffer
330     ConsumedPosition - the number of buffer items that are known to have been fully processed by all users
331     */
332
[5541]333public:
334    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::DynamicBuffer;}
335   
336    DynamicBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t initialCapacity, size_t overflowBlocks = 0, unsigned swizzleFactor = 1, unsigned addrSpace = 0);
[5998]337
338    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
339
340    void releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) const override;
[5541]341   
[5998]342protected:
343
[5650]344    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * avail, bool reverse = false) const override;
[5541]345   
[5782]346    llvm::Value * getLinearlyWritableItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition, llvm::Value * consumed, bool reverse = false) const override;
[5541]347
[5706]348    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * absolutePosition) const override;
[5612]349   
[5755]350    llvm::Value * getBufferedSize(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5612]351   
[5856]352    void doubleCapacity(IDISA::IDISA_Builder * const b, llvm::Value * handle)  const final;
[5541]353
354    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
355   
[5985]356    llvm::Value * getBlockAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const;
[5612]357
[5985]358    llvm::Value * getOverflowAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
[5541]359};
360
361
[4986]362}
363#endif // STREAMSET_H
Note: See TracBrowser for help on using the repository browser.