source: icGREP/icgrep-devel/icgrep/kernels/kernel.cpp @ 4924

Last change on this file since 4924 was 4924, checked in by lindanl, 3 years ago

Add KernelBuilder?.

File size: 8.7 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
6#include "kernel.h"
7#include <iostream>
8
9// sets name & sets internal state to the kernel superclass state
10KernelBuilder::KernelBuilder(std::string name, Module * m, IDISA::IDISA_Builder * b)
11: mMod(m)
12, iBuilder(b)
13, mKernelName(name)
14, mPredifinedStates(2)
15, mBitBlockType(b->getBitBlockType())
16, mBlockSize(b->getBitBlockWidth()){
17    mStates = std::vector<Type *>(4, b->getIntNTy(64)); 
18    mSegmentBlocks = 1;
19    mBufferSize = mSegmentBlocks * mBlockSize;
20}
21
22KernelBuilder::~KernelBuilder(){
23}
24
25int KernelBuilder::extendKernelInternalStateType(Type * t){
26    int idx = mStates.size();
27    mStates.push_back(t);
28    return idx;
29}
30void KernelBuilder::addKernelOutputStream(int fw){
31    if (fw == 1){
32        mOutputStreams.push_back(mBitBlockType);
33    }
34    else {
35        mOutputStreams.push_back(ArrayType::get(mBitBlockType, fw));
36    }
37
38}
39void KernelBuilder::addKernelOutputAccum(Type * t){
40    mOutputAccums.push_back(t);
41
42}
43void KernelBuilder::addKernelInputStream(int fw, std::string name = ""){
44    if (name=="")
45        mInputStreamNames.push_back(name);
46    else
47        mInputStreamNames.push_back(mKernelName + "_inputstream_" + std::to_string(mInputStreams.size()));
48
49    if (fw == 1){
50        mInputStreams.push_back(mBitBlockType);
51    }
52    else {
53        mInputStreams.push_back(ArrayType::get(mBitBlockType, fw));
54    }
55}
56void KernelBuilder::addKernelInputScalar(Type * t, std::string name = ""){
57    if (name=="")
58        mInputScalarNames.push_back(name);
59    else
60        mInputScalarNames.push_back(mKernelName + "_inputscalar_" + std::to_string(mInputScalars.size()));
61
62    mInputScalars.push_back(t);
63}
64
65
66//create doBlock method with empty body and load inputs
67std::vector<std::vector<Value *>> KernelBuilder::openDoBlock(){
68    Type * inputStreamType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), mInputStreams), mSegmentBlocks), 0);
69    Type * inputScalarType = PointerType::get(StructType::get(mMod->getContext(), mInputScalars), 0);
70    Type * outputStreamType = ArrayType::get(StructType::get(mMod->getContext(), mOutputStreams), mSegmentBlocks);
71    Type * outputAccumType = StructType::get(mMod->getContext(), mOutputAccums);
72    Type * stateType = StructType::create(mMod->getContext(), mStates, mKernelName);
73    mKernelStructType = StructType::create(mMod->getContext(),std::vector<Type *>({stateType, outputStreamType, outputAccumType}), "KernelStruct");
74 
75   
76    FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()), 
77        std::vector<Type *>({PointerType::get(mKernelStructType, 0), inputStreamType, inputScalarType}), false); 
78   
79   
80    mDoBlockFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, mKernelName + "_DoBlock", mMod);
81    mDoBlockFunction->setCallingConv(CallingConv::C);
82
83    Function::arg_iterator args = mDoBlockFunction->arg_begin();
84    mKernelStructParam = args++;
85    mKernelStructParam->setName("this");
86    Value* input_stream_param = args++;
87    input_stream_param->setName("input_stream");
88    Value* input_scalar_param = args++;
89    input_scalar_param->setName("input_scalar");
90
91    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mDoBlockFunction,0));
92
93    std::vector<std::vector<Value *>> inputs;
94    for(int j = 0; j<mSegmentBlocks; j++){
95        for(int i = 0; i<mInputStreams.size(); i++){
96            Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(j), iBuilder->getInt32(i)};
97            Value * gep = iBuilder->CreateGEP(input_stream_param, indices);
98            Type * t = gep->getType()->getPointerElementType();
99            if (t != mBitBlockType) {
100                int arraySize = t->getArrayNumElements();
101                inputs.resize(mSegmentBlocks, std::vector<Value *>(arraySize));
102                for (int k=0; k<arraySize; k++){
103                    Value * gep_array_elem = iBuilder->CreateGEP(gep, {iBuilder->getInt32(0), iBuilder->getInt32(k)});
104                    inputs[j][k] = iBuilder->CreateAlignedLoad(gep_array_elem, mBlockSize/8, false, mInputStreamNames.at(i));
105                }
106            }
107            else{
108                inputs.resize(mSegmentBlocks, std::vector<Value *>(mInputStreams.size()));
109                inputs[j][i] = iBuilder->CreateAlignedLoad(gep, mBlockSize/8, false, mInputStreamNames.at(i));
110            }
111           
112        }
113    }
114
115    // for(int i = 0; i<mInputScalars.size(); i++){
116    //     Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(i)};
117    //     Value * gep = iBuilder->CreateGEP(input_scalar_param, indices);
118    // }
119
120    return inputs;
121}
122// void KernelBuilder::closeDoBlock(std::vector<std::vector<Value *>> result){
123
124void KernelBuilder::closeDoBlock(Value * result[][8]){
125    for(int j=0; j<mSegmentBlocks; j++){
126        for(int i = 0; i<mOutputStreams.size(); i++){     
127            Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(1), iBuilder->getInt32(j), iBuilder->getInt32(i)};
128            Value* gep = iBuilder->CreateGEP(mKernelStructParam, indices);
129            iBuilder->CreateAlignedStore(result[j][i], gep, mBlockSize/8, false);
130        }
131    }
132
133    // for(int j=0; j<mSegmentBlocks; j++){
134    //     for(int i = 0; i<mOutputAccums.size(); i++){
135    //         Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(2), iBuilder->getInt32(j), iBuilder->getInt32(i)};
136    //         Value* gep = iBuilder->CreateGEP(mKernelStructType, indices);
137    //         iBuilder->CreateAlignedStore(result[j][i], gep, mBlockSize/8, false);
138    //     }
139    // }
140    iBuilder->CreateRetVoid();
141}
142
143void KernelBuilder::finalizeMethods(){
144    Type * T = iBuilder->getIntNTy(64);
145
146    Constant* c = mMod->getOrInsertFunction(mKernelName+"_Init", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), NULL);
147    Function* mInitFunction = cast<Function>(c);
148    mInitFunction->setCallingConv(CallingConv::C);
149    Function::arg_iterator args = mInitFunction->arg_begin();
150
151    Value* this_param = args++;
152    this_param->setName("this");
153
154    int i = mPredifinedStates;
155    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mInitFunction, 0));
156    Value * gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
157    iBuilder->CreateStore(iBuilder->getInt64(0), gep);  //FileBasePos
158    gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
159    iBuilder->CreateStore(iBuilder->getInt64(0), gep);  //AvailableBlocks
160
161    // while(i < mStates.size()){
162    //     gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(i) }));
163    //     iBuilder->CreateMemSet(gep, iBuilder->getInt8(0), DataLayout::getTypeAllocSize(mStates[i]), 4);
164    // }
165    iBuilder->CreateRetVoid();
166
167    c = mMod->getOrInsertFunction(mKernelName+"_Create_Default", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), T, T, NULL);
168    Function* mConstructor = cast<Function>(c);
169    mConstructor->setCallingConv(CallingConv::C);
170    args = mConstructor->arg_begin();
171
172    this_param = args++;
173    this_param->setName("this");
174    Value* block_size_param = args++;
175    block_size_param->setName("block_size");
176    Value* seg_size_param = args++;
177    seg_size_param->setName("seg_size");
178
179    //initialize blockz_size and seg_size in Constructor not in init function
180    //allocate buffer
181    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mConstructor, 0));
182    gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(0) }));
183    iBuilder->CreateStore(block_size_param, gep);   
184    gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(1) }));
185    iBuilder->CreateStore(seg_size_param, gep); 
186
187    iBuilder->CreateCall(mInitFunction, this_param);
188    iBuilder->CreateRetVoid();
189
190}
191//alloc space & set buffer size
192void KernelBuilder::generateKernelInstance(int segmentBlocks = 1){
193
194    mKernelStruct = iBuilder->CreateAlloca(mKernelStructType); 
195    iBuilder->CreateCall3(mConstructor, mKernelStruct, 
196        ConstantInt::get(iBuilder->getIntNTy(64), mBlockSize), 
197        ConstantInt::get(iBuilder->getIntNTy(64), mBufferSize));
198
199}
200void KernelBuilder::generateInitCall(){
201    iBuilder->CreateCall(mInitFunction, mKernelStruct);
202}
203
204// Value * KernelBuilder::generateDoBlockCall(Value * inputBuffer){
205//     iBuilder->CreateCall3(mDoBlockFunction, mKernelStruct, inputBuffer, outputBuffer);
206//     return outputBuffer;
207// }
208
209int KernelBuilder::getSegmentBlocks(){
210    return mSegmentBlocks;
211}
212
Note: See TracBrowser for help on using the repository browser.