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

Last change on this file since 5440 was 5440, checked in by nmedfort, 2 years ago

Large refactoring step. Removed IR generation code from Kernel (formally KernelBuilder?) and moved it into the new KernelBuilder? class.

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