Ignore:
Timestamp:
Dec 3, 2017, 12:40:40 PM (18 months ago)
Author:
nmedfort
Message:

Bug fixes and simplified MultiBlockKernel? logic

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/kernels/kernel.h

    r5706 r5755  
    1111
    1212namespace llvm { class BasicBlock; }
     13namespace llvm { class Constant; }
    1314namespace llvm { class Function; }
    1415namespace llvm { class IntegerType; }
     
    2627class Kernel : public KernelInterface {
    2728    friend class KernelBuilder;
    28 public:
    29     enum class Port { Input, Output };
    30 
    31     using StreamPort = std::pair<Port, unsigned>;
    32 
    33 protected:
    34 
    35     using KernelMap = boost::container::flat_map<std::string, unsigned>;
    36     using StreamMap = boost::container::flat_map<std::string, StreamPort>;
    37     using StreamSetBuffers = std::vector<parabix::StreamSetBuffer *>;
    38     using Kernels = std::vector<Kernel *>;
     29protected:
    3930
    4031    static const std::string DO_BLOCK_SUFFIX;
     
    5243public:
    5344   
     45    enum class Port { Input, Output };
     46    using StreamPort = std::pair<Port, unsigned>;
     47    using StreamMap = boost::container::flat_map<std::string, StreamPort>;
     48    using KernelFieldMap = boost::container::flat_map<std::string, unsigned>;
     49    using StreamSetBuffers = std::vector<parabix::StreamSetBuffer *>;
     50
    5451    // Kernel Signatures and Module IDs
    5552    //
    5653    // A kernel signature uniquely identifies a kernel and its full functionality.
    5754    // In the event that a particular kernel instance is to be generated and compiled
    58     // to produce object code, and we have a cached kernel object code instance with 
    59     // the same signature and targetting the same IDISA architecture, then the cached 
     55    // to produce object code, and we have a cached kernel object code instance with
     56    // the same signature and targetting the same IDISA architecture, then the cached
    6057    // object code may safely be used to avoid recompilation.
    6158    //
     
    6461    // Kernel developers should take responsibility for designing appropriate signature
    6562    // mechanisms that are short, inexpensive to compute and guarantee uniqueness
    66     // based on the semantics of the kernel. 
     63    // based on the semantics of the kernel.
    6764    //
    6865    // If no other mechanism is available, the default makeSignature() method uses the
     
    8784    // be added, the default method for preparing kernel state may be used.
    8885
    89        
    90     bool isCachable() const override { return false; }
    9186
    9287    std::string makeSignature(const std::unique_ptr<KernelBuilder> & idb) override;
     
    9590    virtual bool hasSignature() const { return true; }
    9691
    97     // Create a module stub for the kernel, populated only with its Module ID.     
    98     //
     92    bool isCachable() const override { return false; }
    9993
    10094    void bindPorts(const StreamSetBuffers & inputs, const StreamSetBuffers & outputs);
    101 
    102     StreamPort getStreamPort(const std::string & name) const;
    10395
    10496    llvm::Module * setModule(llvm::Module * const module);
     
    122114    }
    123115
     116    StreamPort getStreamPort(const std::string & name) const;
     117
     118    const Binding & getBinding(const std::string & name) const;
     119
    124120    const StreamSetBuffers & getStreamSetInputBuffers() const {
    125121        return mStreamSetInputBuffers;
     
    127123
    128124    const parabix::StreamSetBuffer * getStreamSetInputBuffer(const unsigned i) const {
     125        assert (i < mStreamSetInputBuffers.size());
     126        assert (mStreamSetInputBuffers[i]);
    129127        return mStreamSetInputBuffers[i];
     128    }
     129
     130    const parabix::StreamSetBuffer * getInputStreamSetBuffer(const std::string & name) const {
     131        const auto port = getStreamPort(name);
     132        assert (port.first == Port::Input);
     133        return getStreamSetInputBuffer(port.second);
    130134    }
    131135
     
    134138    }
    135139
     140    const Binding & getStreamInput(const unsigned i) const {
     141        return KernelInterface::getStreamInput(i);
     142    }
     143
     144    const Binding & getStreamInput(const std::string & name) const {
     145        const auto port = getStreamPort(name);
     146        assert (port.first == Port::Input);
     147        return KernelInterface::getStreamInput(port.second);
     148    }
     149
    136150    const parabix::StreamSetBuffer * getStreamSetOutputBuffer(const unsigned i) const {
     151        assert (i < mStreamSetOutputBuffers.size());
     152        assert (mStreamSetOutputBuffers[i]);
    137153        return mStreamSetOutputBuffers[i];
     154    }
     155
     156    const parabix::StreamSetBuffer * getOutputStreamSetBuffer(const std::string & name) const {
     157        const auto port = getStreamPort(name);
     158        assert (port.first == Port::Output);
     159        return getStreamSetOutputBuffer(port.second);
     160    }
     161
     162    const Binding & getStreamOutput(const unsigned i) const {
     163        return KernelInterface::getStreamOutput(i);
     164    }
     165
     166    const Binding & getStreamOutput(const std::string & name) const {
     167        const auto port = getStreamPort(name);
     168        assert (port.first == Port::Output);
     169        return KernelInterface::getStreamOutput(port.second);
    138170    }
    139171   
     
    144176    //
    145177   
    146     unsigned getKernelStride() const { return mStride; }
     178    unsigned getStride() const { return mStride; }
    147179   
    148180    virtual ~Kernel() = 0;
     
    156188protected:
    157189
    158     void setKernelStride(unsigned stride) { mStride = stride; }
    159 
    160190    virtual void addInternalKernelProperties(const std::unique_ptr<KernelBuilder> & idb) { }
    161191
     
    163193
    164194    // Constructor
    165     Kernel(std::string && kernelName,
    166                   std::vector<Binding> && stream_inputs,
    167                   std::vector<Binding> && stream_outputs,
    168                   std::vector<Binding> && scalar_parameters,
    169                   std::vector<Binding> && scalar_outputs,
    170                   std::vector<Binding> && internal_scalars);
     195    Kernel(std::string && kernelName, Bindings && stream_inputs,
     196          Bindings && stream_outputs,
     197          Bindings && scalar_parameters,
     198          Bindings && scalar_outputs,
     199          Bindings && internal_scalars);
    171200
    172201    void setNoTerminateAttribute(const bool noTerminate = true) {
     
    174203    }
    175204
    176     llvm::Value * getPrincipleItemCount() const {
    177         return mAvailablePrincipleItemCount;
     205    llvm::Value * getPrincipalItemCount() const {
     206        return mAvailablePrincipalItemCount;
    178207    }
    179208
     
    201230
    202231    void callGenerateFinalizeMethod(const std::unique_ptr<KernelBuilder> & idb);
    203 
    204 
    205     std::pair<unsigned, unsigned> getStreamRate(const Port p, const unsigned i) const;
    206 
    207     const parabix::StreamSetBuffer * getInputStreamSetBuffer(const std::string & name) const {
    208         const auto port = getStreamPort(name);
    209         assert (port.first == Port::Input);
    210         assert (port.second < mStreamSetInputBuffers.size());
    211         assert (mStreamSetInputBuffers[port.second]);
    212         return mStreamSetInputBuffers[port.second];
    213     }
    214 
    215     const parabix::StreamSetBuffer * getOutputStreamSetBuffer(const std::string & name) const {
    216         const auto port = getStreamPort(name);
    217         assert (port.first == Port::Output);
    218         assert (port.second < mStreamSetOutputBuffers.size());
    219         assert (mStreamSetOutputBuffers[port.second]);
    220         return mStreamSetOutputBuffers[port.second];
    221     }
    222232
    223233    const parabix::StreamSetBuffer * getAnyStreamSetBuffer(const std::string & name) const {
     
    235245    }
    236246
    237     llvm::Value * getStreamSetInputBufferPtr(const unsigned i) const {
    238         return mStreamSetInputBufferPtr[i];
    239     }
    240 
    241     llvm::Value * getStreamSetOutputBufferPtr(const unsigned i) const {
    242         return mStreamSetOutputBufferPtr[i];
    243     }
     247    void setStride(unsigned stride) { mStride = stride; }
    244248
    245249private:
    246250
    247251    void addBaseKernelProperties(const std::unique_ptr<KernelBuilder> & idb);
     252
     253    llvm::Value * getStreamSetInputAddress(const std::string & name) const {
     254        const Kernel::StreamPort p = getStreamPort(name);
     255        assert (p.first == Port::Input);
     256        return mStreamSetInputBaseAddress[p.second];
     257    }
     258
     259    llvm::Value * getStreamSetOutputAddress(const std::string & name) const {
     260        const Kernel::StreamPort p = getStreamPort(name);
     261        assert (p.first == Port::Output);
     262        return mStreamSetOutputBaseAddress[p.second];
     263    }
    248264
    249265    llvm::Value * getAvailableItemCount(const unsigned i) const {
     
    251267    }
    252268
     269    void normalizeStreamProcessingRates();
     270
     271    bool normalizeRelativeToFixedProcessingRate(const ProcessingRate & base, ProcessingRate & toUpdate);
     272
    253273protected:
    254274
    255275    llvm::Function *                    mCurrentMethod;
    256     llvm::Value *                       mAvailablePrincipleItemCount;
     276    llvm::Value *                       mAvailablePrincipalItemCount;
    257277    bool                                mNoTerminateAttribute;
    258278    bool                                mIsGenerated;
     
    260280    llvm::Value *                       mIsFinal;
    261281    llvm::Value *                       mOutputScalarResult;
    262 
    263 
    264282    std::vector<llvm::Value *>          mAvailableItemCount;
    265283
     284    KernelFieldMap                      mKernelFieldMap;
    266285    std::vector<llvm::Type *>           mKernelFields;
    267     KernelMap                           mKernelMap;
     286
    268287    StreamMap                           mStreamMap;
     288
    269289    StreamSetBuffers                    mStreamSetInputBuffers;
    270     std::vector<llvm::Value *>          mStreamSetInputBufferPtr;
     290    std::vector<llvm::Value *>          mStreamSetInputBaseAddress;
    271291    StreamSetBuffers                    mStreamSetOutputBuffers;
    272     std::vector<llvm::Value *>          mStreamSetOutputBufferPtr;
    273 
     292    std::vector<llvm::Value *>          mStreamSetOutputBaseAddress;
    274293};
    275294
     295using Kernels = std::vector<Kernel *>;
     296
    276297class SegmentOrientedKernel : public Kernel {
    277298protected:
    278299
    279300    SegmentOrientedKernel(std::string && kernelName,
    280                           std::vector<Binding> && stream_inputs,
    281                           std::vector<Binding> && stream_outputs,
    282                           std::vector<Binding> && scalar_parameters,
    283                           std::vector<Binding> && scalar_outputs,
    284                           std::vector<Binding> && internal_scalars);
     301                          Bindings && stream_inputs,
     302                          Bindings && stream_outputs,
     303                          Bindings && scalar_parameters,
     304                          Bindings && scalar_outputs,
     305                          Bindings && internal_scalars);
    285306protected:
    286307
    287308    void generateKernelMethod(const std::unique_ptr<KernelBuilder> & b) final;
    288309
    289     virtual void generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & kb) = 0;
     310    virtual void generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & b) = 0;
    290311
    291312};
     
    386407
    387408    MultiBlockKernel(std::string && kernelName,
    388                      std::vector<Binding> && stream_inputs,
    389                      std::vector<Binding> && stream_outputs,
    390                      std::vector<Binding> && scalar_parameters,
    391                      std::vector<Binding> && scalar_outputs,
    392                      std::vector<Binding> && internal_scalars);
     409                     Bindings && stream_inputs,
     410                     Bindings && stream_outputs,
     411                     Bindings && scalar_parameters,
     412                     Bindings && scalar_outputs,
     413                     Bindings && internal_scalars);
    393414
    394415    // Each multi-block kernel subtype must provide its own logic for handling
     
    399420    // exit the RetVoid instruction will be added to complete the method.
    400421    //
    401     virtual void generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & idb, llvm::Value * const numOfStrides) = 0;
     422    virtual llvm::Value * generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & b, llvm::Value * const numOfStrides) = 0;
    402423
    403424private:
     
    406427    // method of the multi-block kernel builder makes all the necessary arrangements
    407428    // to translate doSegment calls into a minimal sequence of doMultiBlock calls.
    408     void generateKernelMethod(const std::unique_ptr<KernelBuilder> & kb) final;
     429    void generateKernelMethod(const std::unique_ptr<KernelBuilder> & b) final;
     430
     431    unsigned getItemAlignment(const Binding & binding) const;
     432
     433    ProcessingRate::RateValue getLowerBound(const ProcessingRate &rate) const;
     434
     435    ProcessingRate::RateValue getUpperBound(const ProcessingRate & rate) const;
     436
     437    bool isTransitivelyUnknownRate(const ProcessingRate & rate) const;
     438
     439    llvm::Value * getStrideSize(const std::unique_ptr<KernelBuilder> & b, const ProcessingRate & rate);
    409440
    410441    bool requiresCopyBack(const ProcessingRate & rate) const;
    411442
     443    void reviseFinalProducedItemCounts(const std::unique_ptr<KernelBuilder> & b);
     444
     445protected:
     446
     447    std::vector<llvm::Value *>      mInitialAvailableItemCount;
     448    std::vector<llvm::Value *>      mInitialProcessedItemCount;
     449    std::vector<llvm::Value *>      mInitialProducedItemCount;
     450
    412451};
    413452
     
    416455protected:
    417456
    418     void CreateDoBlockMethodCall(const std::unique_ptr<KernelBuilder> & idb);
     457    void CreateDoBlockMethodCall(const std::unique_ptr<KernelBuilder> & b);
    419458
    420459    // Each kernel builder subtype must provide its own logic for generating
    421460    // doBlock calls.
    422     virtual void generateDoBlockMethod(const std::unique_ptr<KernelBuilder> & idb) = 0;
     461    virtual void generateDoBlockMethod(const std::unique_ptr<KernelBuilder> & b) = 0;
    423462
    424463    // Each kernel builder subtypre must also specify the logic for processing the
     
    429468    // not be overridden.
    430469
    431     virtual void generateFinalBlockMethod(const std::unique_ptr<KernelBuilder> & idb, llvm::Value * remainingItems);
    432 
    433     void generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & idb, llvm::Value * const numOfStrides) final;
     470    virtual void generateFinalBlockMethod(const std::unique_ptr<KernelBuilder> & b, llvm::Value * remainingItems);
    434471
    435472    BlockOrientedKernel(std::string && kernelName,
    436                         std::vector<Binding> && stream_inputs,
    437                         std::vector<Binding> && stream_outputs,
    438                         std::vector<Binding> && scalar_parameters,
    439                         std::vector<Binding> && scalar_outputs,
    440                         std::vector<Binding> && internal_scalars);
     473                        Bindings && stream_inputs,
     474                        Bindings && stream_outputs,
     475                        Bindings && scalar_parameters,
     476                        Bindings && scalar_outputs,
     477                        Bindings && internal_scalars);
    441478
    442479private:
    443480
    444     void writeDoBlockMethod(const std::unique_ptr<KernelBuilder> & idb);
    445 
    446     void writeFinalBlockMethod(const std::unique_ptr<KernelBuilder> & idb, llvm::Value * remainingItems);
     481    llvm::Value * generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & b, llvm::Value * const numOfStrides) final;
     482
     483    void writeDoBlockMethod(const std::unique_ptr<KernelBuilder> & b);
     484
     485    void writeFinalBlockMethod(const std::unique_ptr<KernelBuilder> & b, llvm::Value * remainingItems);
     486
     487    llvm::Value * getRemainingItems(const std::unique_ptr<KernelBuilder> & b);
    447488
    448489private:
    449490
    450     llvm::Function *        mDoBlockMethod;
    451     llvm::BasicBlock *      mStrideLoopBody;
    452     llvm::IndirectBrInst *  mStrideLoopBranch;
    453     llvm::PHINode *         mStrideLoopTarget;
     491    llvm::Function *            mDoBlockMethod;
     492    llvm::BasicBlock *          mStrideLoopBody;
     493    llvm::IndirectBrInst *      mStrideLoopBranch;
     494    llvm::PHINode *             mStrideLoopTarget;
     495    llvm::PHINode *             mStrideBlockIndex;
    454496};
    455497
Note: See TracChangeset for help on using the changeset viewer.