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

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

Moved toolchain and object_cache to kernels directory. Continued work on providing input consumed information.

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