Ignore:
Timestamp:
Mar 15, 2016, 10:20:07 PM (4 years ago)
Author:
nmedfort
Message:

Added the kernel instance class; removed original mmap file access in favour of the boost mmap system. corrected PrintRegister? routine.

File:
1 edited

Legend:

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

    r4970 r4974  
    88#include <IDISA/idisa_builder.h>
    99#include <llvm/Support/CommandLine.h>
     10#include <kernels/instance.h>
    1011
    1112using namespace llvm;
     
    1718    return (x != 0) && (x & (x - 1)) == 0;
    1819}
     20
     21namespace kernel {
    1922
    2023// sets name & sets internal state to the kernel superclass state
     
    3336}
    3437
     38SlabAllocator<Instance> Instance::mAllocator; // static allocator declaration; should probably be in a "instance.cpp"
     39
    3540/** ------------------------------------------------------------------------------------------------------------- *
    3641 * @brief addInternalState
     
    3843unsigned KernelBuilder::addInternalState(Type * const type) {
    3944    assert (type);
    40     const unsigned index = mStates.size();
    41     mStates.push_back(type);
     45    const unsigned index = mInternalState.size();
     46    mInternalState.push_back(type);
    4247    return index;
    4348}
    4449
    45 unsigned KernelBuilder::addInternalState(llvm::Type * const type, std::string name) {
    46     if (LLVM_UNLIKELY(mStateNameMap.count(name) != 0)) {
     50unsigned KernelBuilder::addInternalState(llvm::Type * const type, std::string && name) {
     51    if (LLVM_UNLIKELY(mInternalStateNameMap.count(name) != 0)) {
    4752        throw std::runtime_error("Kernel already contains internal state " + name);
    4853    }
    4954    const unsigned index = addInternalState(type);
    50     mStateNameMap.emplace(name, index);
     55    mInternalStateNameMap.emplace(name, index);
    5156    return index;
    5257}
    5358
    54 /** ------------------------------------------------------------------------------------------------------------- *
    55  * @brief addOutputStream
    56  ** ------------------------------------------------------------------------------------------------------------- */
    57 void KernelBuilder::addOutputStream(const unsigned fields) {
    58     assert (fields > 0);
    59     mOutputStreams.push_back((fields == 1) ? mBitBlockType : ArrayType::get(mBitBlockType, fields));
    60 }
    61 
    62 /** ------------------------------------------------------------------------------------------------------------- *
    63  * @brief addOutputScalar
    64  ** ------------------------------------------------------------------------------------------------------------- */
    65 void KernelBuilder::addOutputScalar(Type * const type) {
    66     assert (type);
    67     mOutputScalar.push_back(type);
    68 }
    69 
    70 /** ------------------------------------------------------------------------------------------------------------- *
    71  * @brief addInputStream
    72  ** ------------------------------------------------------------------------------------------------------------- */
    73 void KernelBuilder::addInputStream(const unsigned fields, std::string name) {
    74     assert (fields > 0 && !name.empty());
    75     mInputStreamNames.push_back(name);
    76     if (fields == 1){
    77         mInputStreams.push_back(mBitBlockType);
    78     } else {
    79         mInputStreams.push_back(ArrayType::get(mBitBlockType, fields));
    80     }
    81 }
    82 
    83 void KernelBuilder::addInputStream(const unsigned fields) {
    84     addInputStream(fields, std::move(mKernelName + "_inputstream_" + std::to_string(mInputStreams.size())));
    85 }
    86 
    87 
    88 /** ------------------------------------------------------------------------------------------------------------- *
    89  * @brief getInputStream
    90  ** ------------------------------------------------------------------------------------------------------------- */
    91 Value * KernelBuilder::getInputStream(const unsigned index, const unsigned streamOffset) {
    92     Value * const indices[] = {getOffset(streamOffset), iBuilder->getInt32(index)};
    93     return iBuilder->CreateGEP(mInputParam, indices);
    94 }
    95 
    96 /** ------------------------------------------------------------------------------------------------------------- *
    97  * @brief getInputScalar
    98  ** ------------------------------------------------------------------------------------------------------------- */
    99 Value * KernelBuilder::getInputScalar(const unsigned) {
    100     throw std::runtime_error("currently not supported!");
    101 }
    102 
    103 /** ------------------------------------------------------------------------------------------------------------- *
    104  * @brief getOutputStream
    105  ** ------------------------------------------------------------------------------------------------------------- */
    106 Value * KernelBuilder::getOutputStream(const unsigned index, const unsigned streamOffset) {
    107     Value * const indices[] = {iBuilder->getInt32(0), iBuilder->getInt32(1), getOffset(streamOffset), iBuilder->getInt32(index)};
    108     return iBuilder->CreateGEP(mKernelParam, indices);
    109 }
    110 
    111 /** ------------------------------------------------------------------------------------------------------------- *
    112  * @brief getOutputScalar
    113  ** ------------------------------------------------------------------------------------------------------------- */
    114 Value * KernelBuilder::getOutputScalar(const unsigned) {
    115     throw std::runtime_error("currently not supported!");
    116 }
    11759
    11860/** ------------------------------------------------------------------------------------------------------------- *
    11961 * @brief getInternalState
    12062 ** ------------------------------------------------------------------------------------------------------------- */
    121 Value * KernelBuilder::getInternalState(const unsigned index, Value * const inputStruct) {
     63Value * KernelBuilder::getInternalState(Value * const instance, const unsigned index) {
    12264    Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(index)};
    123     return iBuilder->CreateGEP(inputStruct ? inputStruct : mKernelParam, indices);
    124 }
    125 
    126 Value * KernelBuilder::getInternalState(const std::string & name, Value * const inputStruct) {
    127     const auto f = mStateNameMap.find(name);
    128     if (LLVM_UNLIKELY(f == mStateNameMap.end())) {
     65    return iBuilder->CreateGEP(instance ? instance : mKernelParam, indices);
     66}
     67
     68Value * KernelBuilder::getInternalState(Value * const instance, const std::string & name) {
     69    const auto f = mInternalStateNameMap.find(name);
     70    if (LLVM_UNLIKELY(f == mInternalStateNameMap.end())) {
    12971        throw std::runtime_error("Kernel does not contain internal state " + name);
    13072    }
    131     return getInternalState(f->second, inputStruct);
     73    return getInternalState(instance, f->second);
    13274}
    13375
     
    13577 * @brief setInternalState
    13678 ** ------------------------------------------------------------------------------------------------------------- */
    137 void KernelBuilder::setInternalState(const unsigned index, Value * const value) {
    138     Value * ptr = getInternalState(index);
     79void KernelBuilder::setInternalState(Value * const instance, const std::string & name, Value * const value) {
     80    Value * ptr = getInternalState(instance, name);
    13981    assert (ptr->getType()->getPointerElementType() == value->getType());
    14082    if (value->getType() == iBuilder->getBitBlockType()) {
     
    14587}
    14688
     89void KernelBuilder::setInternalState(Value * const instance, const unsigned index, Value * const value) {
     90    Value * ptr = getInternalState(instance, index);
     91    assert (ptr->getType()->getPointerElementType() == value->getType());
     92    if (value->getType() == iBuilder->getBitBlockType()) {
     93        iBuilder->CreateBlockAlignedStore(value, ptr);
     94    } else {
     95        iBuilder->CreateStore(value, ptr);
     96    }
     97}
     98
     99/** ------------------------------------------------------------------------------------------------------------- *
     100 * @brief addInputStream
     101 ** ------------------------------------------------------------------------------------------------------------- */
     102void KernelBuilder::addInputStream(const unsigned fields, std::string && name) {
     103    assert (fields > 0 && !name.empty());
     104    mInputStreamName.push_back(name);
     105    if (fields == 1){
     106        mInputStream.push_back(mBitBlockType);
     107    } else {
     108        mInputStream.push_back(ArrayType::get(mBitBlockType, fields));
     109    }
     110}
     111
     112void KernelBuilder::addInputStream(const unsigned fields) {
     113    addInputStream(fields, std::move(mKernelName + "_inputstream_" + std::to_string(mInputStream.size())));
     114}
     115
     116/** ------------------------------------------------------------------------------------------------------------- *
     117 * @brief getInputStream
     118 ** ------------------------------------------------------------------------------------------------------------- */
     119Value * KernelBuilder::getInputStream(llvm::Value * const instance, const unsigned index, const unsigned streamOffset) {
     120    assert (instance);
     121    Value * const indices[] = {getOffset(instance, streamOffset), iBuilder->getInt32(index)};
     122    return iBuilder->CreateGEP(instance, indices);
     123}
     124
    147125/** ------------------------------------------------------------------------------------------------------------- *
    148126 * @brief addInputScalar
    149127 ** ------------------------------------------------------------------------------------------------------------- */
    150 void KernelBuilder::addInputScalar(Type * const type, std::string name) {
     128void KernelBuilder::addInputScalar(Type * const type, std::string && name) {
    151129    assert (type && !name.empty());
    152     mInputScalarNames.push_back(name);
    153     mInputScalars.push_back(type);
     130    mInputScalarName.push_back(name);
     131    mInputScalar.push_back(type);
    154132}
    155133
    156134void KernelBuilder::addInputScalar(Type * const type) {
    157     addInputScalar(type, std::move(mKernelName + "_inputscalar_" + std::to_string(mInputScalars.size())));
     135    addInputScalar(type, std::move(mKernelName + "_inputscalar_" + std::to_string(mInputScalar.size())));
     136}
     137
     138/** ------------------------------------------------------------------------------------------------------------- *
     139 * @brief getInputScalar
     140 ** ------------------------------------------------------------------------------------------------------------- */
     141Value * KernelBuilder::getInputScalar(Value * const instance, const unsigned) {
     142    throw std::runtime_error("currently not supported!");
     143}
     144
     145/** ------------------------------------------------------------------------------------------------------------- *
     146 * @brief addOutputStream
     147 ** ------------------------------------------------------------------------------------------------------------- */
     148unsigned KernelBuilder::addOutputStream(const unsigned fields) {
     149    assert (fields > 0);
     150    const unsigned index = mOutputStream.size();
     151    mOutputStream.push_back((fields == 1) ? mBitBlockType : ArrayType::get(mBitBlockType, fields));
     152    return index;
     153}
     154
     155/** ------------------------------------------------------------------------------------------------------------- *
     156 * @brief addOutputScalar
     157 ** ------------------------------------------------------------------------------------------------------------- */
     158unsigned KernelBuilder::addOutputScalar(Type * const type) {
     159    assert (type);
     160    const unsigned index = mOutputScalar.size();
     161    mOutputScalar.push_back(type);
     162    return index;
     163}
     164
     165/** ------------------------------------------------------------------------------------------------------------- *
     166 * @brief getOutputStream
     167 ** ------------------------------------------------------------------------------------------------------------- */
     168Value * KernelBuilder::getOutputStream(Value * const instance, const unsigned index, const unsigned streamOffset) {
     169    assert (instance);
     170    Value * const indices[] = {getOffset(instance, streamOffset), iBuilder->getInt32(1), iBuilder->getInt32(0), iBuilder->getInt32(index)};
     171    return iBuilder->CreateGEP(instance, indices);
     172}
     173
     174/** ------------------------------------------------------------------------------------------------------------- *
     175 * @brief getOutputStreams
     176 ** ------------------------------------------------------------------------------------------------------------- */
     177Value * KernelBuilder::getOutputStreamSet(Value * const instance, const unsigned streamOffset) {
     178    assert (instance);
     179    Value * const indices[] = {getOffset(instance, streamOffset), iBuilder->getInt32(1)};
     180    return iBuilder->CreateGEP(instance, indices);
     181}
     182
     183/** ------------------------------------------------------------------------------------------------------------- *
     184 * @brief getOutputScalar
     185 ** ------------------------------------------------------------------------------------------------------------- */
     186Value * KernelBuilder::getOutputScalar(Value * const instance, const unsigned) {
     187    throw std::runtime_error("currently not supported!");
    158188}
    159189
     
    167197    const unsigned capacity = mBlocksPerSegment + mCircularBufferModulo - 1;
    168198
    169     mInputStreamType = PointerType::get(StructType::get(mMod->getContext(), mInputStreams), 0);
    170     mInputScalarType = PointerType::get(StructType::get(mMod->getContext(), mInputScalars), 0);
    171     Type * outputStreamType = ArrayType::get(StructType::get(mMod->getContext(), mOutputStreams), capacity);
     199    mInputStreamType = PointerType::get(StructType::get(mMod->getContext(), mInputStream), 0);
     200    mInputScalarType = PointerType::get(StructType::get(mMod->getContext(), mInputScalar), 0);
     201    Type * outputStreamType = ArrayType::get(StructType::get(mMod->getContext(), mOutputStream), capacity);
    172202    Type * outputAccumType = StructType::get(mMod->getContext(), mOutputScalar);
    173     Type * internalStateType = StructType::create(mMod->getContext(), mStates, mKernelName);
     203    Type * internalStateType = StructType::create(mMod->getContext(), mInternalState, mKernelName);
    174204    mKernelStructType = StructType::create(mMod->getContext(),std::vector<Type *>({internalStateType, outputStreamType, outputAccumType}), "KernelStruct_"+ mKernelName);
    175205
     
    205235    iBuilder->CreateRetVoid();
    206236
     237    Type * const int64Ty = iBuilder->getInt64Ty(); // TODO: should call getIntPtrTy() instead but we don't have the data layout here.
     238
    207239    // Generate the zero initializer
    208     Function * initializer = cast<Function>(mMod->getOrInsertFunction(mKernelName + "_Init", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), nullptr));
    209     initializer->setCallingConv(CallingConv::C);
    210     Function::arg_iterator args = initializer->arg_begin();
     240    mConstructor = cast<Function>(mMod->getOrInsertFunction(mKernelName + "_Constructor", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), nullptr));
     241    mConstructor->setCallingConv(CallingConv::C);
     242    auto args = mConstructor->arg_begin();
    211243    mKernelParam = args++;
    212244    mKernelParam->setName("this");
    213 
    214     iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", initializer, 0));
    215 
    216     Type * const int64Ty = iBuilder->getInt64Ty(); // TODO: should call getIntPtrTy() instead but we don't have the data layout here.
    217     for (unsigned i = 0; i < mStates.size(); ++i) {
     245    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mConstructor, 0));
     246    for (unsigned i = 0; i < mInternalState.size(); ++i) {
    218247        Value * const gep = getInternalState(i);
    219248        Type * const type = gep->getType();
    220249        if (type->isIntegerTy() || type->isArrayTy() || type->isVectorTy()) {
    221250            setInternalState(i, Constant::getNullValue(type));
    222         } else {           
     251        } else {
    223252            Value * gep_next = iBuilder->CreateGEP(gep, iBuilder->getInt32(1));
    224253            Value * get_int = iBuilder->CreatePtrToInt(gep, int64Ty);
     
    228257        }
    229258    }
    230 
    231259    iBuilder->CreateRetVoid();
    232260
    233     // and then the constructor
    234     mConstructor = cast<Function>(mMod->getOrInsertFunction(mKernelName+"_Create_Default", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), int64Ty, int64Ty, nullptr));
    235     mConstructor->setCallingConv(CallingConv::C);
    236     args = mConstructor->arg_begin();
    237 
    238     mKernelParam = args++;
    239     mKernelParam->setName("this");
    240 
    241     iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mConstructor, 0));
    242     iBuilder->CreateCall(initializer, mKernelParam);
    243     iBuilder->CreateRetVoid();
    244 }
    245 
    246 /** ------------------------------------------------------------------------------------------------------------- *
    247  * @brief generateKernelInstance
    248  ** ------------------------------------------------------------------------------------------------------------- */
    249 Value * KernelBuilder::generateKernelInstance() {
    250     mKernelStruct = iBuilder->CreateAlloca(mKernelStructType);
    251     iBuilder->CreateCall3(mConstructor, mKernelStruct,
    252         ConstantInt::get(iBuilder->getIntNTy(64), mBlockSize),
    253         ConstantInt::get(iBuilder->getIntNTy(64), (mBlocksPerSegment + mCircularBufferModulo - 1) * mBlockSize));
    254     return mKernelStruct;
    255 }
    256 
    257 /** ------------------------------------------------------------------------------------------------------------- *
    258  * @brief generateDoBlockCall
    259  ** ------------------------------------------------------------------------------------------------------------- */
    260 void KernelBuilder::generateInitCall() {
    261     assert (mInitFunction && mKernelStruct);
    262     iBuilder->CreateCall(mInitFunction, mKernelStruct);
    263 }
    264 
    265 /** ------------------------------------------------------------------------------------------------------------- *
    266  * @brief generateDoBlockCall
    267  ** ------------------------------------------------------------------------------------------------------------- */
    268 void KernelBuilder::generateDoBlockCall(Value * inputStreams) {
    269     assert (mFunction && mKernelStruct);
    270     iBuilder->CreateCall2(mFunction, mKernelStruct, iBuilder->CreatePointerCast(inputStreams, mInputStreamType));
     261    iBuilder->ClearInsertionPoint();
     262
     263    mSegmentIndex = 0;
     264}
     265
     266/** ------------------------------------------------------------------------------------------------------------- *
     267 * @brief instantiate
     268 *
     269 * Generate a new instance of this kernel and call the default constructor to initialize it
     270 ** ------------------------------------------------------------------------------------------------------------- */
     271Instance * KernelBuilder::instantiate() {
     272    AllocaInst * const memory = iBuilder->CreateAlloca(mKernelStructType);
     273    iBuilder->CreateCall(mConstructor, memory);
     274    return new Instance(this, memory);
     275}
     276
     277/** ------------------------------------------------------------------------------------------------------------- *
     278 * @brief call
     279 ** ------------------------------------------------------------------------------------------------------------- */
     280void KernelBuilder::call(llvm::Value * const instance, Value * inputStreams) {
     281    assert (mFunction && instance && inputStreams);
     282    iBuilder->CreateCall2(mFunction, instance, iBuilder->CreatePointerCast(inputStreams, mInputStreamType));
    271283}
    272284
     
    276288 * Compute the stream index of the given offset value.
    277289 ** ------------------------------------------------------------------------------------------------------------- */
    278 Value * KernelBuilder::getOffset(const unsigned value) {
     290Value * KernelBuilder::getOffset(Value * const instance, const unsigned value) {
    279291    const unsigned adjustedOffset = (mSegmentIndex + value);
    280     Value * offset = iBuilder->getInt32(adjustedOffset);
    281292    if (mBlockIndex) {
    282         Value * index = iBuilder->CreateBlockAlignedLoad(getInternalState(mBlockIndex));
     293        Value * offset = iBuilder->CreateBlockAlignedLoad(getBlockNo(instance));
    283294        if (adjustedOffset) {
    284             index = iBuilder->CreateAdd(index, offset);
     295            offset = iBuilder->CreateAdd(offset, ConstantInt::get(offset->getType(), adjustedOffset));
    285296        }
    286297        const unsigned bufferSize = (mBlocksPerSegment + mCircularBufferModulo - 1); assert (bufferSize > 1);
    287298        if (isPowerOfTwo(bufferSize)) {
    288             index = iBuilder->CreateAnd(index, ConstantInt::get(index->getType(), bufferSize - 1));
     299            offset = iBuilder->CreateAnd(offset, ConstantInt::get(offset->getType(), bufferSize - 1));
    289300        } else {
    290             index = iBuilder->CreateURem(index, ConstantInt::get(index->getType(), bufferSize));
     301            offset = iBuilder->CreateURem(offset, ConstantInt::get(offset->getType(), bufferSize));
    291302        }
    292303        // TODO: generate branch / phi node when it's sufficiently unlikely that we'll wrap around.
    293         offset = index;
    294     }
    295     return offset;
     304        return offset;
     305    } else {
     306        return iBuilder->getInt32(adjustedOffset);
     307    }
    296308}
    297309
     
    304316    mCircularBufferModulo = (lookaheadBlocks + 1);
    305317}
     318
     319} // end of namespace kernel
Note: See TracChangeset for help on using the changeset viewer.