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

Last change on this file since 5856 was 5856, checked in by nmedfort, 14 months ago

Revised pipeline structure to better control I/O rates

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