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

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

Use kernel state methods.

File size: 10.3 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(mKernelName + "_inputstream_" + std::to_string(mInputStreams.size()));
46    else
47        mInputStreamNames.push_back(name);
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(mKernelName + "_inputscalar_" + std::to_string(mInputScalars.size()));
59    else
60        mInputScalarNames.push_back(name);
61
62    mInputScalars.push_back(t);
63}
64
65void KernelBuilder::PrepareDoBlockFunction(){ 
66    mInputStreamType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), mInputStreams), mSegmentBlocks), 0);
67    mInputScalarType = PointerType::get(StructType::get(mMod->getContext(), mInputScalars), 0);
68    Type * outputStreamType = ArrayType::get(StructType::get(mMod->getContext(), mOutputStreams), mSegmentBlocks);
69    Type * outputAccumType = StructType::get(mMod->getContext(), mOutputAccums);
70    Type * stateType = StructType::create(mMod->getContext(), mStates, mKernelName);
71    mKernelStructType = StructType::create(mMod->getContext(),std::vector<Type *>({stateType, outputStreamType, outputAccumType}), "KernelStruct_"+mKernelName);
72}
73
74struct Inputs KernelBuilder::openDoBlock(){
75    // FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()),
76    //     std::vector<Type *>({PointerType::get(mKernelStructType, 0), mInputStreamType, mInputScalarType}), false);
77       
78    FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()), 
79        std::vector<Type *>({PointerType::get(mKernelStructType, 0), mInputStreamType}), false); 
80
81    mDoBlockFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, mKernelName + "_DoBlock", mMod);
82    mDoBlockFunction->setCallingConv(CallingConv::C);
83   
84    Function::arg_iterator args = mDoBlockFunction->arg_begin();
85    mKernelStructParam = args++;
86    mKernelStructParam->setName("this");
87    Value* input_stream_param = args++;
88    input_stream_param->setName("input_stream");
89    // Value* input_scalar_param = args++;
90    // input_scalar_param->setName("input_scalar");
91
92    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mDoBlockFunction,0));
93
94    struct Inputs inputs;
95    for(int j = 0; j<mSegmentBlocks; j++){
96        for(int i = 0; i<mInputStreams.size(); i++){
97            Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(j), iBuilder->getInt32(i)};
98            Value * gep = iBuilder->CreateGEP(input_stream_param, indices);
99            Type * t = gep->getType()->getPointerElementType();
100            if (t != mBitBlockType) {
101                int arraySize = t->getArrayNumElements();
102                inputs.streams.resize(mSegmentBlocks, std::vector<valptr>(arraySize));
103                for (int k=0; k<arraySize; k++){
104                    Value * gep_array_elem = iBuilder->CreateGEP(gep, {iBuilder->getInt32(0), iBuilder->getInt32(k)});
105                    inputs.streams[j][k] = iBuilder->CreateAlignedLoad(gep_array_elem, mBlockSize/8, false, mInputStreamNames.at(i));
106                }
107            }
108            else{
109                inputs.streams.resize(mSegmentBlocks, std::vector<valptr>(mInputStreams.size()));
110                inputs.streams[j][i] = iBuilder->CreateAlignedLoad(gep, mBlockSize/8, false, mInputStreamNames.at(i));
111            }
112           
113        }
114    }
115
116    // inputs.scalars.resize(mInputScalars.size());
117    // for(int i = 0; i<mInputScalars.size(); i++){
118    //     Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(i)};
119    //     Value * gep = iBuilder->CreateGEP(input_scalar_param, indices);
120    //     inputs.scalars[i] = iBuilder->CreateAlignedLoad(gep, mBlockSize/8, false, mInputScalarNames.at(i));
121    // }
122
123    return inputs;
124}
125
126void KernelBuilder::closeDoBlock(struct Outputs result){
127   
128
129    for(int j=0; j<mSegmentBlocks; j++){
130        for(int i = 0; i<mOutputStreams.size(); i++){   
131            Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(1), iBuilder->getInt32(j), iBuilder->getInt32(i)};
132            Value* gep = iBuilder->CreateGEP(mKernelStructParam, indices);
133            iBuilder->CreateAlignedStore(result.streams[j][i], gep, mBlockSize/8, false);
134        }
135    }
136
137    for(int i = 0; i<mOutputAccums.size(); i++){   
138        Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(2), iBuilder->getInt32(i)};
139        Value* gep = iBuilder->CreateGEP(mKernelStructParam, indices);
140        iBuilder->CreateAlignedStore(result.accums[i], gep, mBlockSize/8, false);
141    }
142
143    iBuilder->CreateRetVoid();
144}
145
146void KernelBuilder::changeKernelInternalState(Value * kernelStruct, int idx, Value * stateValue){
147    Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(idx)};
148    Value* gep = iBuilder->CreateGEP(kernelStruct, indices);
149    iBuilder->CreateAlignedStore(stateValue, gep, mBlockSize/8, false);
150}
151
152Value * KernelBuilder::getKernelInternalState(Value * kernelStruct, int idx){
153    Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(idx)};
154    Value* gep = iBuilder->CreateGEP(kernelStruct, indices);
155    return iBuilder->CreateAlignedLoad(gep, mBlockSize/8, false, "state"+std::to_string(idx));
156}
157
158Value * KernelBuilder::getKernelInternalStatePtr(Value * kernelStruct, int idx){
159    Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(idx)};
160    Value* gep = iBuilder->CreateGEP(kernelStruct, indices);
161    return gep;
162}
163
164void KernelBuilder::finalizeMethods(){
165    Type * T = iBuilder->getIntNTy(64);
166
167    Constant* c = mMod->getOrInsertFunction(mKernelName+"_Init", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), NULL);
168    Function* mInitFunction = cast<Function>(c);
169    mInitFunction->setCallingConv(CallingConv::C);
170    Function::arg_iterator args = mInitFunction->arg_begin();
171
172    Value* this_param = args++;
173    this_param->setName("this");
174
175    int i = mPredifinedStates;
176    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mInitFunction, 0));
177    Value * gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
178    iBuilder->CreateStore(iBuilder->getInt64(0), gep);  //FileBasePos
179    gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
180    iBuilder->CreateStore(iBuilder->getInt64(0), gep);  //AvailableBlocks
181
182    while(i < mStates.size()){
183        gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
184        Value * gep_next = iBuilder->CreateGEP(gep, std::vector<Value *>({iBuilder->getInt32(1)}));
185        Value * get_int = iBuilder->CreatePtrToInt(gep, T);
186        Value * get_next_int = iBuilder->CreatePtrToInt(gep_next, T);
187        Value * state_size = iBuilder->CreateSub(get_next_int, get_int);
188        iBuilder->CreateMemSet(gep, iBuilder->getInt8(0), state_size, 4);
189    }
190
191    iBuilder->CreateRetVoid();
192
193    c = mMod->getOrInsertFunction(mKernelName+"_Create_Default", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), T, T, NULL);
194    mConstructor = cast<Function>(c);
195    mConstructor->setCallingConv(CallingConv::C);
196    args = mConstructor->arg_begin();
197
198    this_param = args++;
199    this_param->setName("this");
200    Value* block_size_param = args++;
201    block_size_param->setName("block_size");
202    Value* seg_size_param = args++;
203    seg_size_param->setName("seg_size");
204 
205    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mConstructor, 0));
206    gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(0) }));
207    iBuilder->CreateStore(block_size_param, gep);   
208    gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(1) }));
209    iBuilder->CreateStore(seg_size_param, gep); 
210
211    iBuilder->CreateCall(mInitFunction, this_param);
212    iBuilder->CreateRetVoid();
213
214}
215
216Value * KernelBuilder::generateKernelInstance(){
217
218    mKernelStruct = iBuilder->CreateAlloca(mKernelStructType); 
219    iBuilder->CreateCall3(mConstructor, mKernelStruct, 
220        ConstantInt::get(iBuilder->getIntNTy(64), mBlockSize), 
221        ConstantInt::get(iBuilder->getIntNTy(64), mBufferSize));
222    return mKernelStruct;
223
224}
225void KernelBuilder::generateInitCall(){
226    iBuilder->CreateCall(mInitFunction, mKernelStruct);
227}
228
229// void KernelBuilder::generateDoBlockCall(Value * inputStreams, Value * inputScalars){
230//     iBuilder->CreateCall3(mDoBlockFunction, mKernelStruct, inputStreams, inputScalars);
231// }
232void KernelBuilder::generateDoBlockCall(Value * inputStreams){
233    iBuilder->CreateCall2(mDoBlockFunction, mKernelStruct, inputStreams);
234}
235
236int KernelBuilder::getSegmentBlocks(){
237    return mSegmentBlocks;
238}
239
240Function * KernelBuilder::getDoBlockFunction(){
241    return mDoBlockFunction;
242}
243
244Type * KernelBuilder::getKernelStructType(){
245    return mKernelStructType;
246}
247
248Value * KernelBuilder::getKernelStructParam(){
249    return mKernelStructParam;
250}
251
Note: See TracBrowser for help on using the repository browser.