source: icGREP/icgrep-devel/icgrep/kernels/lz4/lz4_block_decoder.cpp @ 5864

Last change on this file since 5864 was 5864, checked in by xwa163, 15 months ago

Add LZ4D extract deposit related kernel, target and test cases

File size: 7.9 KB
Line 
1//
2// Created by wxy325 on 2017/6/25.
3//
4
5#include "lz4_block_decoder.h"
6
7#include <kernels/kernel_builder.h>
8#include <iostream>
9#include <string>
10#include <llvm/Support/raw_ostream.h>
11#include <kernels/streamset.h>
12
13using namespace llvm;
14using namespace kernel;
15using namespace std;
16
17namespace kernel{
18
19LZ4BlockDecoderKernel::LZ4BlockDecoderKernel(const std::unique_ptr<kernel::KernelBuilder> &iBuilder)
20: MultiBlockKernel("lz4BlockDecoder",
21    // Inputs
22    {Binding{iBuilder->getStreamSetTy(1, 8), "byteStream"}},
23    //Outputs
24    {
25        Binding{iBuilder->getStreamSetTy(1, 1), "isCompressed", BoundedRate(0, 1)},
26        Binding{iBuilder->getStreamSetTy(1, 64), "blockStart", BoundedRate(0, 1)},
27        Binding{iBuilder->getStreamSetTy(1, 64), "blockEnd", BoundedRate(0, 1)}},
28    //Arguments
29    {
30        Binding{iBuilder->getInt1Ty(), "hasBlockChecksum"},
31        Binding{iBuilder->getSizeTy(), "headerSize"}
32    },
33    {},
34    //Internal states:
35    {
36    Binding{iBuilder->getInt1Ty(), "hasSkipHeader"},
37    Binding{iBuilder->getSizeTy(), "previousOffset"},
38    Binding{iBuilder->getInt1Ty(), "reachFinalBlock"},
39    })
40, wordWidth{iBuilder->getSizeTy()->getBitWidth()} {
41//    setNoTerminateAttribute(true);
42}
43
44void LZ4BlockDecoderKernel::generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> &iBuilder, Value * const numOfStrides) {
45    BasicBlock * entry_block = iBuilder->GetInsertBlock();
46//    iBuilder->CallPrintInt("block_available", iBuilder->getAvailableItemCount("byteStream"));
47    BasicBlock * exit_block = iBuilder->CreateBasicBlock("exit");
48
49    BasicBlock * assert_fail_block = iBuilder->CreateBasicBlock("assert_fail_block");
50    BasicBlock * real_entry_block = iBuilder->CreateBasicBlock("real_entry_block");
51
52    Value* hasSkipHeader = iBuilder->getScalarField("hasSkipHeader");
53    Value* skipLength = iBuilder->CreateSelect(hasSkipHeader, iBuilder->getSize(0), iBuilder->getScalarField("headerSize"));
54    iBuilder->setScalarField("hasSkipHeader", iBuilder->getInt1(true));
55    skipLength = iBuilder->CreateAdd(skipLength, iBuilder->getScalarField("previousOffset"));
56
57    Value* availableItemCount = iBuilder->getAvailableItemCount("byteStream");
58    Value* processedItemCount = iBuilder->getProcessedItemCount("byteStream");
59    Value* totalItemCount = iBuilder->CreateAdd(availableItemCount, processedItemCount);
60
61
62    BasicBlock * block_decoder_entry = iBuilder->CreateBasicBlock("block_decoder_entry_block");
63    iBuilder->CreateBr(block_decoder_entry);
64
65    // block decoder entry
66    iBuilder->SetInsertPoint(block_decoder_entry);
67
68
69    BasicBlock * block_decoder_con = iBuilder->CreateBasicBlock("block_decoder_con_block");
70    iBuilder->CreateBr(block_decoder_con);
71    iBuilder->SetInsertPoint(block_decoder_con);
72
73    PHINode* sOffset = iBuilder->CreatePHI(iBuilder->getSizeTy(), 2);
74    iBuilder->setScalarField("previousOffset", sOffset);
75    sOffset->addIncoming(skipLength, block_decoder_entry);
76
77    BasicBlock * block_decoder_body = iBuilder->CreateBasicBlock("block_decoder_body_block");
78    BasicBlock * block_decoder_exit = iBuilder->CreateBasicBlock("block_decoder_exit_block");
79    BasicBlock * block_decoder_final = iBuilder->CreateBasicBlock("block_decoder_final_block");
80
81
82    Value* reachFinalBlock = iBuilder->getScalarField("reachFinalBlock");
83
84    iBuilder->CreateCondBr(
85        iBuilder->CreateAnd(
86            iBuilder->CreateICmpULT(sOffset, totalItemCount),
87            iBuilder->CreateNot(reachFinalBlock)
88        ),
89        block_decoder_body,
90        block_decoder_exit);
91
92    //block_decoder_body
93    iBuilder->SetInsertPoint(block_decoder_body);
94    Value* currentBlockSize = iBuilder->getSize(0);
95    for (size_t i = 0; i < 4; i++) {
96        Value* offset = iBuilder->CreateAdd(sOffset, iBuilder->getSize(i));
97        Value* rawOffset = iBuilder->CreateZExt(this->generateLoadInput(iBuilder, offset), iBuilder->getSizeTy());
98
99        currentBlockSize = iBuilder->CreateAdd(currentBlockSize, iBuilder->CreateShl(rawOffset, iBuilder->getSize(8 * i)));
100    }
101
102    Value* realBlockSize = iBuilder->CreateAnd(currentBlockSize, 0x7fffffff);
103    Value* highestBit = iBuilder->CreateTrunc(iBuilder->CreateLShr(currentBlockSize, 31), iBuilder->getInt1Ty());
104    Value* isCompressed = iBuilder->CreateNot(highestBit);
105
106    Value* isFinalBlock = iBuilder->CreateICmpEQ(realBlockSize, iBuilder->getSize(0));
107    iBuilder->setScalarField("reachFinalBlock", isFinalBlock);
108
109    BasicBlock * block_decoder_output_block = iBuilder->CreateBasicBlock("block_decoder_output_block");
110
111    iBuilder->CreateCondBr(isFinalBlock, block_decoder_final, block_decoder_output_block);
112
113    // block_decoder_output_block
114    iBuilder->SetInsertPoint(block_decoder_output_block);
115    Value* blockStart = iBuilder->CreateAdd(sOffset, iBuilder->getSize(4));
116    Value* blockEnd = iBuilder->CreateAdd(blockStart, realBlockSize);
117    this->appendOutput(iBuilder, isCompressed, blockStart, blockEnd);
118    iBuilder->CreateBr(block_decoder_final);
119
120    // block_decoder_final_block
121    iBuilder->SetInsertPoint(block_decoder_final);
122
123    Value* newOffset = sOffset;
124    newOffset = iBuilder->CreateAdd(newOffset, iBuilder->getSize(4)); // Block Size
125    newOffset = iBuilder->CreateAdd(newOffset, realBlockSize); // Block Content
126    newOffset = iBuilder->CreateAdd(
127            newOffset,
128            iBuilder->CreateSelect(
129                    iBuilder->getScalarField("hasBlockChecksum"),
130                    iBuilder->getSize(4),
131                    iBuilder->getSize(0))
132    ); // Block Checksum
133
134    sOffset->addIncoming(newOffset, block_decoder_final);
135    iBuilder->CreateBr(block_decoder_con);
136
137    // block_decoder_exit_block
138    iBuilder->SetInsertPoint(block_decoder_exit);
139
140
141    iBuilder->CreateBr(exit_block);
142    iBuilder->SetInsertPoint(exit_block);
143}
144
145
146    Value* LZ4BlockDecoderKernel::generateLoadInput(const std::unique_ptr<KernelBuilder> & iBuilder, llvm::Value* offset) {
147        // TODO adjust input loading
148        Value * inputBufferBasePtr = iBuilder->getRawInputPointer("byteStream", iBuilder->getSize(0));
149//        offset = iBuilder->CreateSub(iBuilder->getProcessedItemCount("byteStream"), offset);
150        Value* targetPtr = iBuilder->CreateGEP(inputBufferBasePtr, offset);
151        return iBuilder->CreateLoad(targetPtr);
152    }
153
154    Value* LZ4BlockDecoderKernel::appendOutput(const std::unique_ptr<KernelBuilder> & iBuilder, Value* isCompressed, Value* blockStart, Value* blockEnd) {
155        // TODO adjust output storing
156        this->generateStoreCircularOutput(iBuilder, "isCompressed", iBuilder->getInt1Ty()->getPointerTo(), isCompressed);
157        this->generateStoreCircularOutput(iBuilder, "blockStart", iBuilder->getInt64Ty()->getPointerTo(), iBuilder->CreateTruncOrBitCast(blockStart, iBuilder->getInt64Ty()));
158        this->generateStoreCircularOutput(iBuilder, "blockEnd", iBuilder->getInt64Ty()->getPointerTo(), blockEnd);
159    }
160
161    void LZ4BlockDecoderKernel::generateStoreCircularOutput(const unique_ptr<KernelBuilder> &iBuilder, const string& outputBufferName, Type* pointerType, Value* value) {
162        Value* offset = iBuilder->getProducedItemCount(outputBufferName);
163
164        size_t inputSize = this->getOutputBufferSize(iBuilder, outputBufferName);
165        Value* offsetMask = iBuilder->getSize(inputSize - 1);
166        Value* maskedOffset = iBuilder->CreateAnd(offsetMask, offset);
167
168        Value* outputBufferPtr = iBuilder->getRawOutputPointer(outputBufferName, iBuilder->getSize(0));
169
170        outputBufferPtr = iBuilder->CreatePointerCast(outputBufferPtr, pointerType);
171        iBuilder->CreateStore(value, iBuilder->CreateGEP(outputBufferPtr, maskedOffset));
172
173        offset = iBuilder->CreateAdd(offset, iBuilder->getSize(1));
174        iBuilder->setProducedItemCount(outputBufferName, offset);
175    }
176
177    size_t LZ4BlockDecoderKernel::getOutputBufferSize(const unique_ptr<KernelBuilder> &iBuilder, const string& bufferName) {
178        size_t s = this->getOutputStreamSetBuffer(bufferName)->getBufferBlocks();
179        return this->getOutputStreamSetBuffer(bufferName)->getBufferBlocks() * iBuilder->getStride();
180    }
181}
Note: See TracBrowser for help on using the repository browser.