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

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

Replaced stdin input stream with mmap'ed buffer and aligned each read call to the page size.

File size: 5.8 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 size_t round_up_to_nearest(const size_t x, const size_t y) {
13    return (((x - 1) | (y - 1)) + 1);
14}
15
16namespace kernel {
17
18void StdInKernel::generateDoSegmentMethod(Value * /* doFinal */, const std::vector<Value *> & /* producerPos */) {
19
20    BasicBlock * const entryBlock = iBuilder->GetInsertBlock();
21    BasicBlock * const readBlock = CreateBasicBlock("ReadMoreData");
22    BasicBlock * const setTermination = CreateBasicBlock("SetTermination");
23    BasicBlock * const stdInExit = CreateBasicBlock("StdInExit");
24
25    ConstantInt * const segmentSize = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
26    Value * bufferedSize = getScalarField("BufferedSize");
27    Value * const itemsAlreadyRead = getProducedItemCount("codeUnitBuffer");
28    Value * const bytesAlreadyRead = iBuilder->CreateMul(itemsAlreadyRead, iBuilder->getSize(mCodeUnitWidth / 8));
29    Value * unreadSize = iBuilder->CreateSub(bufferedSize, bytesAlreadyRead);
30    Value * const exaustedBuffer = iBuilder->CreateICmpULT(unreadSize, segmentSize);
31    iBuilder->CreateUnlikelyCondBr(exaustedBuffer, readBlock, stdInExit);
32
33    iBuilder->SetInsertPoint(readBlock);
34    // how many pages are required to have enough data for the segment plus one overflow block?
35    const auto PageAlignedSegmentSize = round_up_to_nearest((mSegmentBlocks + 1) * iBuilder->getBitBlockWidth() * (mCodeUnitWidth / 8), getpagesize());
36    ConstantInt * const bytesToRead = iBuilder->getSize(PageAlignedSegmentSize);
37    reserveBytes("codeUnitBuffer", bytesToRead);
38    BasicBlock * const readExit = iBuilder->GetInsertBlock();
39
40    Value * const ptr = getRawOutputPointer("codeUnitBuffer", iBuilder->getInt32(0), bufferedSize);
41    Value * const bytePtr = iBuilder->CreatePointerCast(ptr, iBuilder->getInt8PtrTy());
42    Value * const bytesRead = iBuilder->CreateReadCall(iBuilder->getInt32(STDIN_FILENO), bytePtr, bytesToRead);
43
44    unreadSize = iBuilder->CreateAdd(unreadSize, bytesRead);
45    bufferedSize = iBuilder->CreateAdd(bufferedSize, bytesRead);
46    setScalarField("BufferedSize", bufferedSize);
47    iBuilder->CreateUnlikelyCondBr(iBuilder->CreateICmpULT(unreadSize, segmentSize), setTermination, stdInExit);
48
49    iBuilder->SetInsertPoint(setTermination);
50    Value * const itemsRemaining = iBuilder->CreateUDiv(unreadSize, iBuilder->getSize(mCodeUnitWidth / 8));
51    setTerminationSignal();
52    iBuilder->CreateBr(stdInExit);
53
54    stdInExit->moveAfter(iBuilder->GetInsertBlock());
55
56    iBuilder->SetInsertPoint(stdInExit);
57    PHINode * const produced = iBuilder->CreatePHI(itemsAlreadyRead->getType(), 3);
58
59    produced->addIncoming(segmentSize, entryBlock);
60    produced->addIncoming(segmentSize, readExit);
61    produced->addIncoming(itemsRemaining, setTermination);
62    Value * const itemsRead = iBuilder->CreateAdd(itemsAlreadyRead, produced);
63
64    setProducedItemCount("codeUnitBuffer", itemsRead);
65}
66
67StdInKernel::StdInKernel(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
68: SegmentOrientedKernel(iBuilder, "stdin_source", {}, {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {Binding{iBuilder->getSizeTy(), "BufferedSize"}})
69, mSegmentBlocks(blocksPerSegment)
70, mCodeUnitWidth(codeUnitWidth) {
71   
72}
73
74void FileSource::generateInitMethod() {
75    BasicBlock * setTerminationOnFailure = CreateBasicBlock("setTerminationOnFailure");
76    BasicBlock * fileSourceInitExit = CreateBasicBlock("fileSourceInitExit");
77    Value * handle = iBuilder->CreateFOpenCall(getScalarField("fileName"), iBuilder->CreateGlobalStringPtr("r"));
78    setScalarField("IOstreamPtr", handle);
79    Value * failure = iBuilder->CreateICmpEQ(iBuilder->CreatePtrToInt(handle, iBuilder->getSizeTy()), iBuilder->getSize(0));
80    iBuilder->CreateCondBr(failure, setTerminationOnFailure, fileSourceInitExit);
81    iBuilder->SetInsertPoint(setTerminationOnFailure);
82    setTerminationSignal();
83    iBuilder->CreateBr(fileSourceInitExit);
84    iBuilder->SetInsertPoint(fileSourceInitExit);
85}
86   
87void FileSource::generateDoSegmentMethod(Value * /* doFinal */, const std::vector<Value *> & /* producerPos */) {
88
89    BasicBlock * closeFile = CreateBasicBlock("closeFile");
90    BasicBlock * fileSourceExit = CreateBasicBlock("fileSourceExit");
91    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth/8);
92   
93    Value * produced = getProducedItemCount("codeUnitBuffer");
94    Value * bytePtr = getOutputStreamBlockPtr("codeUnitBuffer", iBuilder->getInt32(0));
95    bytePtr = iBuilder->CreatePointerCast(bytePtr, iBuilder->getInt8PtrTy());
96
97    Value * IOstreamPtr = getScalarField("IOstreamPtr");
98    Value * itemsToDo = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
99    Value * nRead = iBuilder->CreateFReadCall(bytePtr, itemsToDo, itemBytes, IOstreamPtr);
100    produced = iBuilder->CreateAdd(produced, nRead);
101    setProducedItemCount("codeUnitBuffer", produced);
102    Value * lessThanFullSegment = iBuilder->CreateICmpULT(nRead, itemsToDo);
103    iBuilder->CreateCondBr(lessThanFullSegment, closeFile, fileSourceExit);
104
105    iBuilder->SetInsertPoint(closeFile);
106    iBuilder->CreateFCloseCall(IOstreamPtr);
107    setTerminationSignal();
108    iBuilder->CreateBr(fileSourceExit);
109   
110    iBuilder->SetInsertPoint(fileSourceExit);
111   
112}
113   
114FileSource::FileSource(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
115: SegmentOrientedKernel(iBuilder, "filesink", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {},
116                {Binding{iBuilder->getInt8PtrTy(), "fileName"}}, {}, {Binding{iBuilder->getFILEptrTy(), "IOstreamPtr"}})
117, mSegmentBlocks(blocksPerSegment)
118, mCodeUnitWidth(codeUnitWidth) {
119}
120
121}
Note: See TracBrowser for help on using the repository browser.