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

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

Progress on multi-block kernels, including support for SourceBuffers?

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