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

Last change on this file since 5757 was 5757, checked in by nmedfort, 17 months ago

Bug fixes + more assertions to prevent similar errors.

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