source: icGREP/icgrep-devel/icgrep/kernels/lzparabix/LZParabixBlockDecoder.cpp @ 6114

Last change on this file since 6114 was 6114, checked in by xwa163, 13 months ago

Init check in for new compression format (lzparabix) related kernels and pipelines, including compressor, decoder and grep

File size: 6.7 KB
Line 
1//
2// Created by wxy325 on 2018/6/18.
3//
4
5#include "LZParabixBlockDecoder.h"
6#include <kernels/kernel_builder.h>
7#include <iostream>
8#include <string>
9#include <llvm/Support/raw_ostream.h>
10#include <kernels/streamset.h>
11
12using namespace llvm;
13using namespace kernel;
14using namespace std;
15
16namespace kernel{
17
18    LZParabixBlockDecoderKernel::LZParabixBlockDecoderKernel(const std::unique_ptr<kernel::KernelBuilder> &iBuilder, std::string&& kernelName)
19            : SegmentOrientedKernel(std::string(kernelName),
20// Inputs
21                                    {
22                                            Binding{iBuilder->getStreamSetTy(1, 8), "byteStream"},
23                                    },
24//Outputs
25                                    {
26                                            Binding{iBuilder->getStreamSetTy(1, 64), "blockStart", BoundedRate(0, 1)},
27                                            Binding{iBuilder->getStreamSetTy(1, 64), "blockEnd", RateEqualTo("blockStart")}},
28//Arguments
29                                    {
30                                            Binding{iBuilder->getSizeTy(), "fileSize"}
31                                    },
32                                    {},
33//Internal states:
34                                    {
35                                            Binding{iBuilder->getSizeTy(), "previousOffset"},
36                                            Binding{iBuilder->getInt1Ty(), "reachFinalBlock"},
37
38                                            Binding{iBuilder->getInt64Ty(), "pendingBlockStart"},
39                                            Binding{iBuilder->getInt64Ty(), "pendingBlockEnd"},
40                                    }) {
41
42    }
43
44    void LZParabixBlockDecoderKernel::appendOutput(const std::unique_ptr<KernelBuilder> & iBuilder, Value * const blockStart, Value * const blockEnd) {
45        Value * const offset = iBuilder->getProducedItemCount("blockStart");
46        generateStoreNumberOutput(iBuilder, "blockStart", offset, blockStart);
47        generateStoreNumberOutput(iBuilder, "blockEnd", offset, blockEnd);
48        iBuilder->setProducedItemCount("blockStart", iBuilder->CreateAdd(offset, iBuilder->getSize(1)));
49    }
50
51    llvm::Value *LZParabixBlockDecoderKernel::generateLoadInput(const std::unique_ptr<KernelBuilder> &iBuilder,
52                                                                llvm::Value *offset) {
53        return iBuilder->CreateLoad(iBuilder->getRawInputPointer("byteStream", offset));
54    }
55
56    void LZParabixBlockDecoderKernel::generateStoreNumberOutput(const unique_ptr<KernelBuilder> &iBuilder, const string &outputBufferName, Value * offset, Value *value) {
57        iBuilder->CreateStore(value, iBuilder->getRawOutputPointer(outputBufferName, offset));
58    }
59
60    void LZParabixBlockDecoderKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> &b) {
61        Constant* INT64_0 = b->getInt64(0);
62
63        BasicBlock * entryBlock = b->GetInsertBlock();
64
65        // Skip Header
66        Value* previousOffset = b->getScalarField("previousOffset");
67        Value* initBlockStart = b->getScalarField("pendingBlockStart");
68        Value* initBlockEnd = b->getScalarField("pendingBlockEnd");
69        Value * availableItemCount = b->getAvailableItemCount("byteStream");
70        BasicBlock * processCon = b->CreateBasicBlock("process_con");
71        b->CreateBr(processCon);
72
73        b->SetInsertPoint(processCon);
74
75        PHINode* phiBlockStart = b->CreatePHI(initBlockStart->getType(), 3);
76        PHINode* phiBlockEnd = b->CreatePHI(initBlockEnd->getType(), 3);
77        PHINode* sOffset = b->CreatePHI(previousOffset->getType(), 3);
78
79        phiBlockStart->addIncoming(initBlockStart, entryBlock);
80        phiBlockEnd->addIncoming(initBlockEnd, entryBlock);
81        sOffset->addIncoming(previousOffset, entryBlock);
82
83        // Store Output
84        BasicBlock* storeOutputBlock = b->CreateBasicBlock("storeOutputBlock");
85        BasicBlock * block_decoder_con = b->CreateBasicBlock("block_decoder_con_block");
86
87        b->CreateUnlikelyCondBr(
88                b->CreateAnd(
89                        b->CreateICmpULE(phiBlockEnd, availableItemCount),
90                        b->CreateNot(b->CreateICmpEQ(phiBlockEnd, INT64_0))
91                ),
92                storeOutputBlock,
93                block_decoder_con
94        );
95
96        b->SetInsertPoint(storeOutputBlock);
97
98        appendOutput(b, phiBlockStart, phiBlockEnd);
99
100
101        phiBlockStart->addIncoming(INT64_0, storeOutputBlock);
102        phiBlockEnd->addIncoming(INT64_0, storeOutputBlock);
103        sOffset->addIncoming(sOffset, storeOutputBlock);
104
105        b->CreateBr(processCon);
106
107
108        // block decoder entry
109        b->SetInsertPoint(block_decoder_con);
110
111        BasicBlock * block_decoder_body = b->CreateBasicBlock("block_decoder_body_block");
112        BasicBlock * block_decoder_exit = b->CreateBasicBlock("block_decoder_exit_block");
113
114        Value * reachFinalBlock = b->getScalarField("reachFinalBlock");
115        b->CreateCondBr(
116                b->CreateAnd(
117                        b->CreateICmpULT(sOffset, availableItemCount),
118                        b->CreateNot(reachFinalBlock)
119                ),
120                block_decoder_body,
121                block_decoder_exit);
122
123        //block_decoder_body
124        b->SetInsertPoint(block_decoder_body);
125        Value* currentBlockSize = b->getSize(0);
126        for (size_t i = 0; i < 4; i++) {
127            Value * offset = b->CreateAdd(sOffset, b->getSize(i));
128            Value * rawOffset = b->CreateZExt(generateLoadInput(b, offset), b->getSizeTy());
129            currentBlockSize = b->CreateOr(currentBlockSize, b->CreateShl(rawOffset, b->getSize(8 * i)));
130        }
131
132        Value * realBlockSize = currentBlockSize;
133
134        Value * isFinalBlock = b->CreateICmpEQ(realBlockSize, b->getSize(0));
135        b->setScalarField("reachFinalBlock", isFinalBlock);
136
137        Value * blockStart = b->CreateAdd(sOffset, b->getSize(4));
138        Value * blockEnd = b->CreateAdd(blockStart, realBlockSize);
139
140        Value * newOffset = sOffset;
141        newOffset = b->CreateAdd(newOffset, b->getSize(4)); // Block Size
142        newOffset = b->CreateAdd(newOffset, realBlockSize); // Block Content
143
144        sOffset->addIncoming(newOffset, block_decoder_body);
145        phiBlockStart->addIncoming(blockStart, block_decoder_body);
146        phiBlockEnd->addIncoming(blockEnd, block_decoder_body);
147        b->CreateBr(processCon);
148
149        // block_decoder_exit_block
150        b->SetInsertPoint(block_decoder_exit);
151        b->setScalarField("pendingBlockStart", phiBlockStart);
152        b->setScalarField("pendingBlockEnd", phiBlockEnd);
153        b->setScalarField("previousOffset", sOffset);
154        b->setProcessedItemCount("byteStream", availableItemCount);
155        b->setTerminationSignal(mIsFinal);
156    }
157
158}
Note: See TracBrowser for help on using the repository browser.