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

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

Encode BitStream? directly in LZParabix compressed file

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.