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

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

Multiblock kernels use whole block copy to/from temp buffers; allow input stream sets with variable rates

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