source: icGREP/icgrep-devel/icgrep/kernels/casefold_pipeline.cpp @ 4988

Last change on this file since 4988 was 4988, checked in by cameron, 3 years ago

casefold sample application/pipeline

File size: 7.0 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 <kernels/casefold_pipeline.h>
7#include <utf_encoding.h>
8
9#include <kernels/s2p_kernel.h>
10#include <kernels/p2s_kernel.h>
11#include <kernels/stdout_kernel.h>
12#include <kernels/instance.h>
13
14#include <pablo/function.h>
15#include <pablo/pablo_compiler.h>
16#include <pablo/pablo_toolchain.h>
17
18static cl::opt<unsigned> SegmentSize("segment-size", cl::desc("Segment Size"), cl::value_desc("positive integer"), cl::init(1));
19
20
21using namespace pablo;
22using namespace kernel;
23
24PipelineBuilder::PipelineBuilder(Module * m, IDISA::IDISA_Builder * b)
25: mMod(m)
26, iBuilder(b)
27, mBitBlockType(b->getBitBlockType())
28, mBlockSize(b->getBitBlockWidth()){
29
30}
31
32PipelineBuilder::~PipelineBuilder(){
33    delete mS2PKernel;
34    delete mCaseFoldKernel;
35    delete mP2SKernel;
36    delete mStdOutKernel;
37}
38
39void PipelineBuilder::CreateKernels(PabloFunction * function){
40    mS2PKernel = new KernelBuilder("s2p", mMod, iBuilder, SegmentSize);
41    mP2SKernel = new KernelBuilder("p2s", mMod, iBuilder, SegmentSize);
42    mCaseFoldKernel = new KernelBuilder("casefold", mMod, iBuilder, SegmentSize);
43    mStdOutKernel = new KernelBuilder("stddout", mMod, iBuilder, SegmentSize);
44
45    generateS2PKernel(mMod, iBuilder, mS2PKernel);
46    generateP2SKernel(mMod, iBuilder, mP2SKernel);
47    generateStdOutKernel(mMod, iBuilder, mStdOutKernel);
48
49    pablo_function_passes(function);
50
51    PabloCompiler pablo_compiler(mMod, iBuilder);
52    try {
53        pablo_compiler.setKernel(mCaseFoldKernel);
54        pablo_compiler.compile(function);
55        delete function;
56        releaseSlabAllocatorMemory();
57    } catch (std::runtime_error e) {
58        delete function;
59        releaseSlabAllocatorMemory();
60        std::cerr << "Runtime error: " << e.what() << std::endl;
61        exit(1);
62    }
63   
64}
65
66Function *  PipelineBuilder::ExecuteKernels() {
67    Type * const int64ty = iBuilder->getInt64Ty();
68    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
69    Type * const inputType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), std::vector<Type *>({ArrayType::get(mBitBlockType, 8)})), 1), 0);
70   
71    Function * const main = cast<Function>(mMod->getOrInsertFunction("Main", Type::getVoidTy(mMod->getContext()), inputType, int64ty, nullptr));
72    main->setCallingConv(CallingConv::C);
73    Function::arg_iterator args = main->arg_begin();
74   
75    Value * const inputStream = args++;
76    inputStream->setName("input");
77    Value * const bufferSize = args++;
78    bufferSize->setName("bufferSize");
79   
80    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", main,0));
81   
82    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
83
84    BasicBlock * segmentCondBlock = nullptr;
85    BasicBlock * segmentBodyBlock = nullptr;
86    const unsigned segmentSize = SegmentSize;
87    if (segmentSize > 1) {
88        segmentCondBlock = BasicBlock::Create(mMod->getContext(), "segmentCond", main, 0);
89        segmentBodyBlock = BasicBlock::Create(mMod->getContext(), "segmentBody", main, 0);
90    }
91    BasicBlock * fullCondBlock = BasicBlock::Create(mMod->getContext(), "fullCond", main, 0);
92    BasicBlock * fullBodyBlock = BasicBlock::Create(mMod->getContext(), "fullBody", main, 0);
93    BasicBlock * finalBlock = BasicBlock::Create(mMod->getContext(), "final", main, 0);
94    BasicBlock * finalPartialBlock = BasicBlock::Create(mMod->getContext(), "partial", main, 0);
95    BasicBlock * finalEmptyBlock = BasicBlock::Create(mMod->getContext(), "empty", main, 0);
96    BasicBlock * endBlock = BasicBlock::Create(mMod->getContext(), "end", main, 0);
97
98    Instance * s2pInstance = mS2PKernel->instantiate(inputStream);
99    Instance * caseFoldInstance = mCaseFoldKernel->instantiate(s2pInstance->getOutputStreamSet());
100    Instance * p2sInstance = mP2SKernel->instantiate(caseFoldInstance->getOutputStreamSet());
101    Instance * stdOutInstance = mStdOutKernel->instantiate(p2sInstance->getOutputStreamSet());
102
103    stdOutInstance->setInternalState("RemainingBytes", bufferSize);  // The total number of bytes to be sent to stdout.
104
105   
106    Value * initialBufferSize = nullptr;
107    BasicBlock * initialBlock = nullptr;
108   
109    if (segmentSize > 1) {
110        iBuilder->CreateBr(segmentCondBlock);
111        iBuilder->SetInsertPoint(segmentCondBlock);
112        PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
113        remainingBytes->addIncoming(bufferSize, entryBlock);
114        Constant * const step = ConstantInt::get(int64ty, mBlockSize * segmentSize);
115        Value * segmentCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
116        iBuilder->CreateCondBr(segmentCondTest, fullCondBlock, segmentBodyBlock);
117        iBuilder->SetInsertPoint(segmentBodyBlock);
118        for (unsigned i = 0; i < segmentSize; ++i) {
119            s2pInstance->CreateDoBlockCall();
120        }
121        for (unsigned i = 0; i < segmentSize; ++i) {
122            caseFoldInstance->CreateDoBlockCall();
123        }
124        for (unsigned i = 0; i < segmentSize; ++i) {
125            p2sInstance->CreateDoBlockCall();
126        }
127        for (unsigned i = 0; i < segmentSize; ++i) {
128            stdOutInstance->CreateDoBlockCall();
129        }
130        remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), segmentBodyBlock);
131        iBuilder->CreateBr(segmentCondBlock);
132        initialBufferSize = remainingBytes;
133        initialBlock = segmentCondBlock;
134    } else {
135        initialBufferSize = bufferSize;
136        initialBlock = entryBlock;
137        iBuilder->CreateBr(fullCondBlock);
138    }
139
140    iBuilder->SetInsertPoint(fullCondBlock);
141    PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
142    remainingBytes->addIncoming(initialBufferSize, initialBlock);
143    //iBuilder->CallPrintInt("remainingBytes", iBuilder->CreatePtrToInt(remainingBytes, iBuilder->getInt64Ty()));
144
145    Constant * const step = ConstantInt::get(int64ty, mBlockSize);
146    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
147    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
148   
149    iBuilder->SetInsertPoint(fullBodyBlock);
150
151    s2pInstance->CreateDoBlockCall();
152    caseFoldInstance->CreateDoBlockCall();
153    p2sInstance->CreateDoBlockCall();
154    stdOutInstance->CreateDoBlockCall();
155
156    Value * diff = iBuilder->CreateSub(remainingBytes, step);
157
158    remainingBytes->addIncoming(diff, fullBodyBlock);
159    iBuilder->CreateBr(fullCondBlock);
160   
161    iBuilder->SetInsertPoint(finalBlock);
162    Value * emptyBlockCond = iBuilder->CreateICmpEQ(remainingBytes, ConstantInt::get(int64ty, 0));
163    iBuilder->CreateCondBr(emptyBlockCond, finalEmptyBlock, finalPartialBlock);
164   
165   
166    iBuilder->SetInsertPoint(finalPartialBlock);
167    s2pInstance->CreateDoBlockCall();
168    iBuilder->CreateBr(endBlock);
169   
170    iBuilder->SetInsertPoint(finalEmptyBlock);
171    s2pInstance->clearOutputStream();
172    iBuilder->CreateBr(endBlock);
173   
174    iBuilder->SetInsertPoint(endBlock);
175
176    caseFoldInstance->CreateDoBlockCall();
177    p2sInstance->CreateDoBlockCall();
178    stdOutInstance->CreateDoBlockCall();
179    iBuilder->CreateRetVoid();
180    return main;
181}
Note: See TracBrowser for help on using the repository browser.