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

Last change on this file since 5377 was 5377, checked in by nmedfort, 2 years ago

Support for stdin. Needs more testing.

File size: 4.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
12inline static unsigned ceil_log2(const unsigned v) {
13    assert ("log2(0) is undefined!" && v != 0);
14    return 32 - __builtin_clz(v - 1);
15}
16
17namespace kernel {
18
19void StdInKernel::generateDoSegmentMethod(Value * /* doFinal */, const std::vector<Value *> & /* producerPos */) {
20
21    BasicBlock * setTermination = CreateBasicBlock("setTermination");
22    BasicBlock * stdInExit = CreateBasicBlock("stdInExit");
23    ConstantInt * segmentItems = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth() / mCodeUnitWidth);
24    ConstantInt * segmentItems2 = iBuilder->getSize(2 * mSegmentBlocks * iBuilder->getBitBlockWidth() / mCodeUnitWidth);
25    // on the first segment, we buffer twice the data necessary to ensure that we can safely check for a non-LF line break
26    Value * itemsRead = getProducedItemCount("codeUnitBuffer");
27    Value * isFirst = iBuilder->CreateICmpEQ(itemsRead, iBuilder->getSize(0));
28    Value * itemsToRead = iBuilder->CreateSelect(isFirst, segmentItems2, segmentItems);
29
30    Value * segmentBytes = reserveItemCount("codeUnitBuffer", itemsToRead);
31    Value * bytePtr =  getOutputStreamBlockPtr("codeUnitBuffer", iBuilder->getInt32(0));
32    bytePtr = iBuilder->CreatePointerCast(bytePtr, iBuilder->getInt8PtrTy());
33    Value * bytesRead = iBuilder->CreateReadCall(iBuilder->getInt32(STDIN_FILENO), bytePtr, segmentBytes);
34    itemsRead = iBuilder->CreateAdd(itemsRead, iBuilder->CreateUDiv(bytesRead, iBuilder->getSize(mCodeUnitWidth / 8)));
35
36    iBuilder->CreateCondBr(iBuilder->CreateICmpEQ(bytesRead, iBuilder->getSize(0)), setTermination, stdInExit);
37    iBuilder->SetInsertPoint(setTermination);
38    setTerminationSignal();
39    iBuilder->CreateBr(stdInExit);
40    iBuilder->SetInsertPoint(stdInExit);
41
42    setProducedItemCount("codeUnitBuffer", itemsRead);
43}
44
45StdInKernel::StdInKernel(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
46: SegmentOrientedKernel(iBuilder, "stdin_source", {}, {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {})
47, mSegmentBlocks(blocksPerSegment)
48, mCodeUnitWidth(codeUnitWidth) {
49   
50}
51
52void FileSource::generateInitMethod() {
53    BasicBlock * setTerminationOnFailure = CreateBasicBlock("setTerminationOnFailure");
54    BasicBlock * fileSourceInitExit = CreateBasicBlock("fileSourceInitExit");
55    Value * handle = iBuilder->CreateFOpenCall(getScalarField("fileName"), iBuilder->CreateGlobalStringPtr("r"));
56    setScalarField("IOstreamPtr", handle);
57    Value * failure = iBuilder->CreateICmpEQ(iBuilder->CreatePtrToInt(handle, iBuilder->getSizeTy()), iBuilder->getSize(0));
58    iBuilder->CreateCondBr(failure, setTerminationOnFailure, fileSourceInitExit);
59    iBuilder->SetInsertPoint(setTerminationOnFailure);
60    setTerminationSignal();
61    iBuilder->CreateBr(fileSourceInitExit);
62    iBuilder->SetInsertPoint(fileSourceInitExit);
63}
64   
65void FileSource::generateDoSegmentMethod(Value * /* doFinal */, const std::vector<Value *> & /* producerPos */) {
66
67    BasicBlock * closeFile = CreateBasicBlock("closeFile");
68    BasicBlock * fileSourceExit = CreateBasicBlock("fileSourceExit");
69    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth/8);
70   
71    Value * produced = getProducedItemCount("codeUnitBuffer");
72    Value * bytePtr = getOutputStreamBlockPtr("codeUnitBuffer", iBuilder->getInt32(0));
73    bytePtr = iBuilder->CreatePointerCast(bytePtr, iBuilder->getInt8PtrTy());
74
75    Value * IOstreamPtr = getScalarField("IOstreamPtr");
76    Value * itemsToDo = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
77    Value * nRead = iBuilder->CreateFReadCall(bytePtr, itemsToDo, itemBytes, IOstreamPtr);
78    produced = iBuilder->CreateAdd(produced, nRead);
79    setProducedItemCount("codeUnitBuffer", produced);
80    Value * lessThanFullSegment = iBuilder->CreateICmpULT(nRead, itemsToDo);
81    iBuilder->CreateCondBr(lessThanFullSegment, closeFile, fileSourceExit);
82
83    iBuilder->SetInsertPoint(closeFile);
84    iBuilder->CreateFCloseCall(IOstreamPtr);
85    setTerminationSignal();
86    iBuilder->CreateBr(fileSourceExit);
87   
88    iBuilder->SetInsertPoint(fileSourceExit);
89   
90}
91   
92FileSource::FileSource(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
93: SegmentOrientedKernel(iBuilder, "filesink", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {},
94                {Binding{iBuilder->getInt8PtrTy(), "fileName"}}, {}, {Binding{iBuilder->getFILEptrTy(), "IOstreamPtr"}})
95, mSegmentBlocks(blocksPerSegment)
96, mCodeUnitWidth(codeUnitWidth) {
97}
98
99}
Note: See TracBrowser for help on using the repository browser.