source: icGREP/icgrep-devel/icgrep/kernels/stdout_kernel.cpp @ 5217

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

Merged PabloFunction? and PabloKernel? classes. Updated projects where necessary.

File size: 6.7 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#include <kernels/stdout_kernel.h>
6#include <kernels/kernel.h>
7#include <IDISA/idisa_builder.h>
8
9namespace kernel {
10
11static Function * create_write(Module * const mod, IDISA::IDISA_Builder * builder) {
12    Function * write = mod->getFunction("write");
13    if (write == nullptr) {
14        IntegerType * sizeTy = builder->getSizeTy();
15        IntegerType * int32Ty = builder->getInt32Ty();
16        PointerType * int8PtrTy = builder->getInt8PtrTy();
17        write = cast<Function>(mod->getOrInsertFunction("write",
18                                 AttributeSet().addAttribute(mod->getContext(), 2U, Attribute::NoAlias),
19                                 sizeTy, int32Ty, int8PtrTy, sizeTy, nullptr));
20    }
21    return write;
22}
23
24// The doBlock method is deprecated.   But in case it is used, just call doSegment with
25// 1 as the number of blocks to do.
26void stdOutKernel::generateDoBlockMethod() {
27    auto savePoint = iBuilder->saveIP();
28    Module * m = iBuilder->getModule();
29    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
30    Function * doSegmentFunction = m->getFunction(mKernelName + doSegment_suffix);
31    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
32    Value * self = getParameter(doBlockFunction, "self");
33    iBuilder->CreateCall(doSegmentFunction, {self, ConstantInt::get(iBuilder->getSizeTy(), 1)});
34    iBuilder->CreateRetVoid();
35    iBuilder->restoreIP(savePoint);
36}
37           
38// Rather than using doBlock logic to write one block at a time, this custom
39// doSegment method, writes the entire segment with a single write call.
40void stdOutKernel::generateDoSegmentMethod() {
41    auto savePoint = iBuilder->saveIP();
42    Module * m = iBuilder->getModule();
43    Function * writefn = create_write(m, iBuilder);
44    Function * doSegmentFunction = m->getFunction(mKernelName + doSegment_suffix);
45    Type * i8PtrTy = iBuilder->getInt8PtrTy();
46   
47    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doSegmentFunction, 0));
48    BasicBlock * setTermination = BasicBlock::Create(iBuilder->getContext(), "setTermination", doSegmentFunction, 0);
49    BasicBlock * stdOutexit = BasicBlock::Create(iBuilder->getContext(), "stdOutexit", doSegmentFunction, 0);
50    Constant * blockItems = ConstantInt::get(iBuilder->getSizeTy(), iBuilder->getBitBlockWidth());
51    Constant * itemBytes = ConstantInt::get(iBuilder->getSizeTy(), mCodeUnitWidth/8);
52   
53    Function::arg_iterator args = doSegmentFunction->arg_begin();
54    Value * self = &*(args++);
55    Value * blocksToDo = &*(args);
56    ////iBuilder->CallPrintInt("blocksToDo", blocksToDo);
57    Value * segmentNo = getLogicalSegmentNo(self);
58    Value * streamStructPtr = getStreamSetStructPtr(self, "codeUnitBuffer");
59    //iBuilder->CallPrintInt("streamStructPtr", iBuilder->CreatePtrToInt(streamStructPtr, iBuilder->getInt64Ty()));
60
61    LoadInst * producerPos = iBuilder->CreateAtomicLoadAcquire(mStreamSetInputBuffers[0]->getProducerPosPtr(streamStructPtr));
62    //iBuilder->CallPrintInt("producerPos", producerPos);
63    Value * processed = getProcessedItemCount(self);
64    Value * itemsAvail = iBuilder->CreateSub(producerPos, processed);
65    Value * itemsMax = iBuilder->CreateMul(blocksToDo, blockItems);
66    Value * lessThanFullSegment = iBuilder->CreateICmpULT(itemsAvail, itemsMax);
67    Value * itemsToDo = iBuilder->CreateSelect(lessThanFullSegment, itemsAvail, itemsMax);
68   
69    Value * blockNo = getScalarField(self, blockNoScalar);
70    //iBuilder->CallPrintInt("blockNo", blockNo);
71    Value * basePtr = getStreamSetBlockPtr(self, "codeUnitBuffer", blockNo);
72    //iBuilder->CallPrintInt("basePtr", iBuilder->CreatePtrToInt(basePtr, iBuilder->getInt64Ty()));
73    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
74    Value * bytePtr = iBuilder->CreateGEP(iBuilder->CreateBitCast(basePtr, i8PtrTy), byteOffset);
75
76    iBuilder->CreateCall(writefn, std::vector<Value *>({iBuilder->getInt32(1), bytePtr, iBuilder->CreateMul(itemsToDo, itemBytes)}));
77   
78    processed = iBuilder->CreateAdd(processed, itemsToDo);
79    setProcessedItemCount(self, processed);
80    setScalarField(self, blockNoScalar, iBuilder->CreateUDiv(processed, blockItems));
81    mStreamSetInputBuffers[0]->setConsumerPos(streamStructPtr, processed);
82
83    Value * endSignal = iBuilder->CreateLoad(mStreamSetInputBuffers[0]->getEndOfInputPtr(streamStructPtr));
84    Value * inFinalSegment = iBuilder->CreateAnd(endSignal, lessThanFullSegment);
85   
86    iBuilder->CreateCondBr(inFinalSegment, setTermination, stdOutexit);
87    iBuilder->SetInsertPoint(setTermination);
88
89    setTerminationSignal(self);
90
91    iBuilder->CreateBr(stdOutexit);
92    iBuilder->SetInsertPoint(stdOutexit);
93    // Must be the last action, for synchronization.
94    setLogicalSegmentNo(self, iBuilder->CreateAdd(segmentNo, ConstantInt::get(iBuilder->getSizeTy(), 1)));
95    iBuilder->CreateRetVoid();
96    iBuilder->restoreIP(savePoint);
97}
98
99void stdOutKernel::generateFinalBlockMethod() {
100    auto savePoint = iBuilder->saveIP();
101    Module * m = iBuilder->getModule();
102    Function * writefn = create_write(m, iBuilder);
103    Function * finalBlockFunction = m->getFunction(mKernelName + finalBlock_suffix);
104    Type * i8PtrTy = iBuilder->getInt8PtrTy();
105   
106    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "fb_flush", finalBlockFunction, 0));
107    Constant * blockItems = ConstantInt::get(iBuilder->getSizeTy(), iBuilder->getBitBlockWidth());
108    Constant * itemBytes = ConstantInt::get(iBuilder->getSizeTy(), mCodeUnitWidth/8);
109    Value * self = getParameter(finalBlockFunction, "self");
110    Value * streamStructPtr = getStreamSetStructPtr(self, "codeUnitBuffer");
111    LoadInst * producerPos = iBuilder->CreateAtomicLoadAcquire(mStreamSetInputBuffers[0]->getProducerPosPtr(streamStructPtr));
112    Value * processed = getProcessedItemCount(self);
113    Value * itemsAvail = iBuilder->CreateSub(producerPos, processed);
114//    Value * segmentNo = getLogicalSegmentNo(self);
115    Value * blockNo = getScalarField(self, blockNoScalar);
116    Value * basePtr = getStreamSetBlockPtr(self, "codeUnitBuffer", blockNo);
117    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
118    Value * bytePtr = iBuilder->CreateGEP(iBuilder->CreateBitCast(basePtr, i8PtrTy), byteOffset);
119    iBuilder->CreateCall(writefn, std::vector<Value *>({iBuilder->getInt32(1), bytePtr, iBuilder->CreateMul(itemsAvail, itemBytes)}));
120    setProcessedItemCount(self, producerPos);
121    mStreamSetInputBuffers[0]->setConsumerPos(streamStructPtr, producerPos);
122    setTerminationSignal(self);
123    iBuilder->CreateRetVoid();
124    iBuilder->restoreIP(savePoint);
125}
126}
Note: See TracBrowser for help on using the repository browser.