source: icGREP/icgrep-devel/icgrep/kernels/stdin_kernel.cpp @ 5281

Last change on this file since 5281 was 5281, checked in by cameron, 2 years ago

Stdin kernel: initial check-in

File size: 6.7 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#include <kernels/stdin_kernel.h>
6#include <llvm/IR/Module.h>
7#include <kernels/kernel.h>
8#include <IR_Gen/idisa_builder.h>
9
10using namespace llvm;
11
12namespace kernel {
13   
14void StdInKernel::generateDoSegmentMethod() const {
15    auto savePoint = iBuilder->saveIP();
16    Module * m = iBuilder->getModule();
17    Function * doSegmentFunction = m->getFunction(mKernelName + doSegment_suffix);
18    Type * i8PtrTy = iBuilder->getInt8PtrTy();
19   
20    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doSegmentFunction, 0));
21    BasicBlock * setTermination = BasicBlock::Create(iBuilder->getContext(), "setTermination", doSegmentFunction, 0);
22    BasicBlock * stdInExit = BasicBlock::Create(iBuilder->getContext(), "stdInExit", doSegmentFunction, 0);
23    Constant * blockItems = ConstantInt::get(iBuilder->getSizeTy(), iBuilder->getBitBlockWidth());
24    Constant * itemBytes = ConstantInt::get(iBuilder->getSizeTy(), mCodeUnitWidth/8);
25    Constant * segmentBytes = ConstantInt::get(iBuilder->getSizeTy(),
26                                               mSegmentBlocks * iBuilder->getBitBlockWidth() * mCodeUnitWidth/8);
27    Constant * stdin_fileno = iBuilder->getInt32(STDIN_FILENO);
28    Function::arg_iterator args = doSegmentFunction->arg_begin();
29    Value * self = &*(args++);
30   
31    Value * produced = getProducedItemCount(self, "codeUnitBuffer");
32    Value * blockNo = iBuilder->CreateUDiv(produced, blockItems);
33    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(produced, blockItems), itemBytes);
34    Value * bytePtr = getStreamView(i8PtrTy, self, "codeUnitBuffer", blockNo, byteOffset);
35   
36    Value * nRead = iBuilder->CreateReadCall(stdin_fileno, bytePtr, segmentBytes);
37    Value * bytesRead = iBuilder->CreateSelect(iBuilder->CreateICmpSLT(nRead, iBuilder->getSize(0)), iBuilder->getSize(0), nRead);
38    produced = iBuilder->CreateAdd(produced, iBuilder->CreateUDiv(bytesRead, itemBytes));
39    setProducedItemCount(self, "codeUnitBuffer", produced);
40    Value * lessThanFullSegment = iBuilder->CreateICmpULT(bytesRead, segmentBytes);
41    iBuilder->CreateCondBr(lessThanFullSegment, setTermination, stdInExit);
42    iBuilder->SetInsertPoint(setTermination);
43    setTerminationSignal(self);
44    iBuilder->CreateBr(stdInExit);
45   
46    iBuilder->SetInsertPoint(stdInExit);
47    iBuilder->CreateRetVoid();
48    iBuilder->restoreIP(savePoint);
49   
50}
51
52StdInKernel::StdInKernel(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
53: KernelBuilder(iBuilder, "stdin_source", {}, {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {})
54, mSegmentBlocks(blocksPerSegment)
55, mCodeUnitWidth(codeUnitWidth) {
56   
57}
58
59void FileSource::generateInitMethod() const {
60    auto savePoint = iBuilder->saveIP();
61    Module * const m = iBuilder->getModule();
62    Function * initFunction = m->getFunction(mKernelName + init_suffix);
63    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "Init_entry", initFunction, 0));
64    BasicBlock * setTerminationOnFailure = BasicBlock::Create(iBuilder->getContext(), "setTerminationOnFailure", initFunction, 0);
65    BasicBlock * fileSourceInitExit = BasicBlock::Create(iBuilder->getContext(), "fileSourceInitExit", initFunction, 0);
66    Function::arg_iterator args = initFunction->arg_begin();
67    Value * self = &*(args++);
68    iBuilder->CreateStore(ConstantAggregateZero::get(mKernelStateType), self);
69    for (auto binding : mScalarInputs) {
70        Value * param = &*(args++);
71        Value * ptr = iBuilder->CreateGEP(self, {iBuilder->getInt32(0), getScalarIndex(binding.name)});
72        iBuilder->CreateStore(param, ptr);
73    }
74    Value * handle = iBuilder->CreateFOpenCall(getScalarField(self, "fileName"), iBuilder->CreateGlobalStringPtr("r"));
75    setScalarField(self, "IOstreamPtr", handle);
76    Value * failure = iBuilder->CreateICmpEQ(iBuilder->CreatePtrToInt(handle, iBuilder->getSizeTy()), iBuilder->getSize(0));
77    iBuilder->CreateCondBr(failure, setTerminationOnFailure, fileSourceInitExit);
78    iBuilder->SetInsertPoint(setTerminationOnFailure);
79    setTerminationSignal(self);
80    iBuilder->CreateBr(fileSourceInitExit);
81    iBuilder->SetInsertPoint(fileSourceInitExit);
82    iBuilder->CreateRetVoid();
83    iBuilder->restoreIP(savePoint);
84}
85   
86void FileSource::generateDoSegmentMethod() const {
87    auto savePoint = iBuilder->saveIP();
88    Module * m = iBuilder->getModule();
89    Function * doSegmentFunction = m->getFunction(mKernelName + doSegment_suffix);
90    Type * i8PtrTy = iBuilder->getInt8PtrTy();
91   
92    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doSegmentFunction, 0));
93    BasicBlock * closeFile = BasicBlock::Create(iBuilder->getContext(), "closeFile", doSegmentFunction, 0);
94    BasicBlock * fileSourceExit = BasicBlock::Create(iBuilder->getContext(), "fileSourceExit", doSegmentFunction, 0);
95    Constant * blockItems = iBuilder->getSize(iBuilder->getBitBlockWidth());
96    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth/8);
97   
98    Function::arg_iterator args = doSegmentFunction->arg_begin();
99    Value * self = &*(args++);
100    // ignore: Value * doFinal = &*(args++);
101    Value * produced = getProducedItemCount(self, "codeUnitBuffer");
102    Value * blockNo = iBuilder->CreateUDiv(produced, blockItems);
103    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(produced, blockItems), itemBytes);
104    Value * bytePtr = getStreamView(i8PtrTy, self, "codeUnitBuffer", blockNo, byteOffset);
105    Value * IOstreamPtr = getScalarField(self, "IOstreamPtr");
106    Value * itemsToDo = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
107    Value * nRead = iBuilder->CreateFReadCall(bytePtr, itemsToDo, itemBytes, IOstreamPtr);
108    produced = iBuilder->CreateAdd(produced, nRead);
109    setProducedItemCount(self, "codeUnitBuffer", produced);
110    Value * lessThanFullSegment = iBuilder->CreateICmpULT(nRead, itemsToDo);
111    iBuilder->CreateCondBr(lessThanFullSegment, closeFile, fileSourceExit);
112
113    iBuilder->SetInsertPoint(closeFile);
114    iBuilder->CreateFCloseCall(IOstreamPtr);
115    setTerminationSignal(self);
116    iBuilder->CreateBr(fileSourceExit);
117   
118    iBuilder->SetInsertPoint(fileSourceExit);
119    iBuilder->CreateRetVoid();
120    iBuilder->restoreIP(savePoint);
121   
122}
123   
124FileSource::FileSource(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
125: KernelBuilder(iBuilder, "filesink", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, 
126                {Binding{iBuilder->getInt8PtrTy(), "fileName"}}, {}, {Binding{iBuilder->getFILEptrTy(), "IOstreamPtr"}})
127, mSegmentBlocks(blocksPerSegment)
128, mCodeUnitWidth(codeUnitWidth) {
129}
130
131}
Note: See TracBrowser for help on using the repository browser.