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

Last change on this file since 5303 was 5303, checked in by cameron, 3 years ago

Refined copy-back buffers, use copyback in p2s_compressed; stdout/filesink mods for circular buffers

File size: 7.4 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 "stdout_kernel.h"
6#include <llvm/IR/Module.h>
7#include <IR_Gen/idisa_builder.h>
8#include <kernels/streamset.h>
9#include <stdio.h>
10// #include <llvm/IR/Type.h>
11namespace llvm { class Type; }
12
13using namespace llvm;
14using namespace parabix;
15
16namespace kernel {
17           
18// Rather than using doBlock logic to write one block at a time, this custom
19// doSegment method attempts to write the entire segment with a single write call.
20// However, if the segment spans two memory areas (e.g., because of wraparound),
21// then two write calls are made.
22void StdOutKernel::generateDoSegmentMethod(Value *doFinal, const std::vector<Value *> &producerPos) {
23    PointerType * i8PtrTy = iBuilder->getInt8PtrTy();
24
25    Constant * blockItems = iBuilder->getSize(iBuilder->getBitBlockWidth());
26    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth/8);
27   
28    Value * processed = getProcessedItemCount("codeUnitBuffer");
29    Value * itemsToDo = iBuilder->CreateSub(producerPos[0], processed);
30    // There may be two memory areas if we are at the physical end of a circular buffer.
31    auto const &= getStreamSetBuffer("codeUnitBuffer");
32    Value * wraparound = nullptr;
33    if (isa<CircularBuffer>(b) || isa<CircularCopybackBuffer>(b)) {
34        Value * accessible = b->getLinearlyAccessibleItems(processed);
35        wraparound = iBuilder->CreateICmpULT(accessible, itemsToDo);
36        itemsToDo = iBuilder->CreateSelect(wraparound, accessible, itemsToDo);
37    }
38   
39    //Value * blockNo = getBlockNo();
40    Value * blockNo = iBuilder->CreateUDiv(processed, blockItems);
41    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
42    Value * bytePtr = getStreamView(i8PtrTy, "codeUnitBuffer", blockNo, byteOffset);
43    iBuilder->CreateWriteCall(iBuilder->getInt32(1), bytePtr, iBuilder->CreateMul(itemsToDo, itemBytes));
44    processed = iBuilder->CreateAdd(processed, itemsToDo);
45    setProcessedItemCount("codeUnitBuffer", processed);
46    //setBlockNo(iBuilder->CreateUDiv(processed, blockItems));
47   
48    // Now we may process the second area (if required).
49    if (isa<CircularBuffer>(b) || isa<CircularCopybackBuffer>(b)) {
50        BasicBlock * wrapAroundWrite = CreateBasicBlock("wrapAroundWrite");
51        BasicBlock * stdoutExit = CreateBasicBlock("stdoutExit");
52        iBuilder->CreateCondBr(wraparound, wrapAroundWrite, stdoutExit);
53        iBuilder->SetInsertPoint(wrapAroundWrite);
54       
55        // Calculate from the updated value of processed;
56        blockNo = iBuilder->CreateUDiv(processed, blockItems);
57        byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
58        bytePtr = getStreamView(i8PtrTy, "codeUnitBuffer", blockNo, byteOffset);
59        itemsToDo = iBuilder->CreateSub(producerPos[0], processed);
60        iBuilder->CreateWriteCall(iBuilder->getInt32(1), bytePtr, iBuilder->CreateMul(itemsToDo, itemBytes));
61        processed = iBuilder->CreateAdd(processed, itemsToDo);
62        setProcessedItemCount("codeUnitBuffer", producerPos[0]);
63        iBuilder->CreateBr(stdoutExit);
64        iBuilder->SetInsertPoint(stdoutExit);
65    }
66}
67
68StdOutKernel::StdOutKernel(IDISA::IDISA_Builder * iBuilder, unsigned codeUnitWidth)
69: SegmentOrientedKernel(iBuilder, "stdout", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {}, {})
70, mCodeUnitWidth(codeUnitWidth) {
71    setNoTerminateAttribute(true);
72}
73
74void FileSink::generateInitMethod() {
75    BasicBlock * setTerminationOnFailure = CreateBasicBlock("setTerminationOnFailure");
76    BasicBlock * fileSinkInitExit = CreateBasicBlock("fileSinkInitExit");
77    Value * handle = iBuilder->CreateFOpenCall(getScalarField("fileName"), iBuilder->CreateGlobalStringPtr("w"));
78    setScalarField("IOstreamPtr", handle);
79    Value * failure = iBuilder->CreateICmpEQ(iBuilder->CreatePtrToInt(handle, iBuilder->getSizeTy()), iBuilder->getSize(0));
80    iBuilder->CreateCondBr(failure, setTerminationOnFailure, fileSinkInitExit);
81    iBuilder->SetInsertPoint(setTerminationOnFailure);
82    setTerminationSignal();
83    iBuilder->CreateBr(fileSinkInitExit);
84    iBuilder->SetInsertPoint(fileSinkInitExit);
85}
86
87void FileSink::generateDoSegmentMethod(Value *doFinal, const std::vector<Value *> &producerPos) {
88    PointerType * i8PtrTy = iBuilder->getInt8PtrTy();
89   
90    BasicBlock * closeFile = CreateBasicBlock("closeFile");
91    BasicBlock * fileOutExit = CreateBasicBlock("fileOutExit");
92    Constant * blockItems = iBuilder->getSize(iBuilder->getBitBlockWidth());
93    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth/8);
94   
95    Value * IOstreamPtr = getScalarField("IOstreamPtr");
96    Value * processed = getProcessedItemCount("codeUnitBuffer");
97    Value * itemsToDo = iBuilder->CreateSub(producerPos[0], processed);
98    // There may be two memory areas if we are at the physical end of a circular buffer.
99    auto const &= getStreamSetBuffer("codeUnitBuffer");
100    Value * wraparound = nullptr;
101    if (isa<CircularBuffer>(b) || isa<CircularCopybackBuffer>(b)) {
102        Value * accessible = b->getLinearlyAccessibleItems(processed);
103        wraparound = iBuilder->CreateICmpULT(accessible, itemsToDo);
104        itemsToDo = iBuilder->CreateSelect(wraparound, accessible, itemsToDo);
105    }
106   
107    Value * blockNo = iBuilder->CreateUDiv(processed, blockItems);
108    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
109    Value * bytePtr = getStreamView(i8PtrTy, "codeUnitBuffer", blockNo, byteOffset);
110    iBuilder->CreateFWriteCall(bytePtr, itemsToDo, itemBytes, IOstreamPtr);
111   
112   
113    processed = iBuilder->CreateAdd(processed, itemsToDo);
114    setProcessedItemCount("codeUnitBuffer", processed);
115    //setBlockNo(iBuilder->CreateUDiv(processed, blockItems));
116   
117    // Now we may process the second area (if required).
118    if (isa<CircularBuffer>(b) || isa<CircularCopybackBuffer>(b)) {
119        BasicBlock * wrapAroundWrite = CreateBasicBlock("wrapAroundWrite");
120        BasicBlock * checkFinal = CreateBasicBlock("checkFinal");
121        iBuilder->CreateCondBr(wraparound, wrapAroundWrite, checkFinal);
122        iBuilder->SetInsertPoint(wrapAroundWrite);
123       
124        // Calculate from the updated value of processed;
125        blockNo = iBuilder->CreateUDiv(processed, blockItems);
126        byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
127        bytePtr = getStreamView(i8PtrTy, "codeUnitBuffer", blockNo, byteOffset);
128        itemsToDo = iBuilder->CreateSub(producerPos[0], processed);
129        iBuilder->CreateFWriteCall(bytePtr, itemsToDo, itemBytes, IOstreamPtr);
130        processed = iBuilder->CreateAdd(processed, itemsToDo);
131        setProcessedItemCount("codeUnitBuffer", producerPos[0]);
132        iBuilder->CreateBr(checkFinal);
133        iBuilder->SetInsertPoint(checkFinal);
134    }
135    iBuilder->CreateCondBr(doFinal, closeFile, fileOutExit);
136   
137    iBuilder->SetInsertPoint(closeFile);
138    iBuilder->CreateFCloseCall(IOstreamPtr);
139    iBuilder->CreateBr(fileOutExit);
140   
141    iBuilder->SetInsertPoint(fileOutExit);
142}
143
144FileSink::FileSink(IDISA::IDISA_Builder * iBuilder, unsigned codeUnitWidth)
145: SegmentOrientedKernel(iBuilder, "filesink", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {},
146                {Binding{iBuilder->getInt8PtrTy(), "fileName"}}, {}, {Binding{iBuilder->getFILEptrTy(), "IOstreamPtr"}})
147, mCodeUnitWidth(codeUnitWidth) {
148}
149
150}
151
152
153
Note: See TracBrowser for help on using the repository browser.