source: icGREP/icgrep-devel/icgrep/kernels/lz4/lz4_bitstream_match_copy_kernel.cpp @ 6066

Last change on this file since 6066 was 6066, checked in by xwa163, 11 months ago

fix some warning in lz4 related kernels

File size: 21.5 KB
Line 
1
2#include "lz4_bitstream_match_copy_kernel.h"
3
4#include <kernels/kernel_builder.h>
5#include <kernels/streamset.h>
6#include <toolchain/toolchain.h>
7#include <vector>
8#include <llvm/Support/raw_ostream.h>
9#include <llvm/IR/Intrinsics.h>
10
11
12using namespace llvm;
13using namespace std;
14namespace kernel {
15
16    std::vector<llvm::Value *>
17    LZ4BitStreamMatchCopyKernel::loadAllI64BitStreamValues(const std::unique_ptr<KernelBuilder> &b,
18                                                                 llvm::Value *basePtr,
19                                                                 llvm::Value *i64PackIndex) {
20        // TODO use gather to improve performance
21        std::vector<llvm::Value *, allocator<llvm::Value*>> v;
22
23        // For now, assume bit block type is always <4 * i64>
24        Value* bitBlockIndex = b->CreateUDiv(i64PackIndex, b->getSize(4));
25        Value* extractIndex = b->CreateURem(i64PackIndex, b->getSize(4));
26
27        for (unsigned i = 0; i < mNumberOfStreams; i++) {
28            Value* bitBlockPtr =  b->CreateGEP(basePtr, b->CreateAdd(b->CreateMul(bitBlockIndex, b->getSize(mNumberOfStreams)), b->getSize(i)));
29            bitBlockPtr = b->CreatePointerCast(bitBlockPtr, b->getInt64Ty()->getPointerTo());
30            v.push_back(b->CreateLoad(b->CreateGEP(bitBlockPtr, extractIndex)));
31        }
32        return v;
33    }
34
35    Value *LZ4BitStreamMatchCopyKernel::advanceUntilNextBit(const std::unique_ptr<KernelBuilder> &iBuilder, string inputName, Value *startPos, bool isNextOne) {
36        BasicBlock* entryBlock = iBuilder->GetInsertBlock();
37
38        Constant* SIZE_0 = iBuilder->getSize(0);
39        Constant* SIZE_1 = iBuilder->getSize(1);
40        Value* SIZE_64 = iBuilder->getSize(64); // maybe need to handle 32 bit machine
41        Value* SIZE_INPUT_64_COUNT = iBuilder->CreateUDiv(iBuilder->getCapacity(inputName), iBuilder->getSize(64));
42
43        Value* initCurrentPos = startPos;
44
45        Value* offsetMarkerRawPtr = iBuilder->CreatePointerCast(iBuilder->getRawInputPointer(inputName, SIZE_0), iBuilder->getInt64Ty()->getPointerTo());
46
47        BasicBlock* findNextMatchOffsetConBlock = iBuilder->CreateBasicBlock("findNextMatchOffsetConBlock");
48        BasicBlock* findNextMatchOffsetBodyBlock = iBuilder->CreateBasicBlock("findNextMatchOffsetBodyBlock");
49
50        iBuilder->CreateBr(findNextMatchOffsetConBlock);
51        iBuilder->SetInsertPoint(findNextMatchOffsetConBlock);
52        // Find position marker bit of next 1 bit
53
54        PHINode* phiCurrentPos = iBuilder->CreatePHI(iBuilder->getSizeTy(), 2);
55        phiCurrentPos->addIncoming(initCurrentPos, entryBlock);
56
57        Value* currentPosGlobalBlockIndex = iBuilder->CreateUDiv(phiCurrentPos, SIZE_64);
58        Value* currentPosLocalBlockIndex = iBuilder->CreateURem(currentPosGlobalBlockIndex, SIZE_INPUT_64_COUNT);
59        Value* currentPosBlockOffset = iBuilder->CreateURem(phiCurrentPos, SIZE_64);
60        Value* currentValue = iBuilder->CreateLoad(iBuilder->CreateGEP(offsetMarkerRawPtr, currentPosLocalBlockIndex));
61
62        Value* countValue = iBuilder->CreateLShr(currentValue, currentPosBlockOffset);
63        if (!isNextOne) {
64            countValue = iBuilder->CreateNot(countValue);
65        }
66        Value* forwardZero = iBuilder->CreateCountForwardZeroes(countValue);
67        Value* realForwardZero = iBuilder->CreateAdd(currentPosBlockOffset, forwardZero);
68
69        // If targetMarker == 0, move to next block, otherwise count forward zero
70        phiCurrentPos->addIncoming(iBuilder->CreateMul(SIZE_64, iBuilder->CreateAdd(currentPosGlobalBlockIndex, SIZE_1)), iBuilder->GetInsertBlock());
71        iBuilder->CreateCondBr(iBuilder->CreateICmpUGE(realForwardZero, SIZE_64), findNextMatchOffsetConBlock, findNextMatchOffsetBodyBlock);
72
73        iBuilder->SetInsertPoint(findNextMatchOffsetBodyBlock);
74
75        Value* newPosition = iBuilder->CreateAdd(iBuilder->CreateMul(currentPosGlobalBlockIndex, SIZE_64), realForwardZero);
76
77        return newPosition;
78    }
79
80    pair<Value*, Value*> LZ4BitStreamMatchCopyKernel::loadNextMatchOffset(const unique_ptr<KernelBuilder> &iBuilder) {
81        Value* initCurrentPos = iBuilder->CreateAdd(iBuilder->getScalarField("currentOffsetMarkerPos"), iBuilder->getSize(1));
82        Value* newPosition = this->advanceUntilNextBit(iBuilder, "MatchOffsetMarker", initCurrentPos, true);
83
84        // Load Match Offset from newPosition
85        Value* matchOffsetPtr = iBuilder->getRawInputPointer("byteStream", newPosition);
86        // For now, it is safe to cast matchOffset pointer into i16 since the input byte stream is always linear available
87        matchOffsetPtr = iBuilder->CreatePointerCast(matchOffsetPtr, iBuilder->getInt16Ty()->getPointerTo());
88        Value* matchOffset = iBuilder->CreateZExt(iBuilder->CreateLoad(matchOffsetPtr), iBuilder->getSizeTy());
89
90        return std::make_pair(matchOffset, newPosition);
91    }
92
93
94    void LZ4BitStreamMatchCopyKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & b) {
95        // ---- Contant
96        ConstantInt * const SIZE_4_MEGS = b->getSize(4 * 1024 * 1024);
97        ConstantInt * const SIZE_0 = b->getSize(0);
98        ConstantInt * const SIZE_1 = b->getSize(1);
99        ConstantInt * const SIZE_64 = b->getSize(64);
100        ConstantInt * const INT64_0 = b->getInt64(0);
101        ConstantInt * const INT64_1 = b->getInt64(1);
102
103        // ---- Type
104        Type* BITBLOCK_TYPE = b->getBitBlockType();
105        Type* BITBLOCK_PTR_TYPE = BITBLOCK_TYPE->getPointerTo();
106        Type* I64_TY = b->getInt64Ty();
107        Type* I64_PTR_TY = I64_TY->getPointerTo();
108
109        Value * PDEP_func = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_bmi_pdep_64); //TODO for now only consider 64 bits
110
111        // ---- EntryBlock
112        BasicBlock * const entryBlock = b->GetInsertBlock();
113        BasicBlock * const exitBlock = b->CreateBasicBlock("exitBlock");
114
115        Value * const available = b->getAvailableItemCount("inputBitStream");
116        Value * const processed = b->getProcessedItemCount("inputBitStream");
117
118        Value * const itemsToDo = b->CreateUMin(b->CreateSub(available, processed), SIZE_4_MEGS);
119        b->setTerminationSignal(b->CreateICmpULT(itemsToDo, SIZE_4_MEGS));
120
121
122        Value* m0MarkerBasePtr = b->CreatePointerCast(b->getInputStreamBlockPtr("M0Marker", SIZE_0), I64_PTR_TY); // i64*
123        Value* sourceStreamPtr = b->CreatePointerCast(b->getInputStreamBlockPtr("inputBitStream", SIZE_0), BITBLOCK_PTR_TYPE);
124        Value* outputStreamPtr = b->CreatePointerCast(b->getOutputStreamBlockPtr("outputBitStream", SIZE_0), BITBLOCK_PTR_TYPE);
125
126        BasicBlock * const processLoopCon = b->CreateBasicBlock("processLoopCon");
127        BasicBlock * const processLoopBody = b->CreateBasicBlock("processLoopBody");
128        BasicBlock * const processLoopExit = b->CreateBasicBlock("processLoopExit");
129
130        b->CreateBr(processLoopCon);
131
132        // ---- ProcessLoopCon
133        // ProcessLoop will process one block of data each time (64bit m0, <4 * i64> input and output data)
134        b->SetInsertPoint(processLoopCon);
135
136        // carryBit === 0x1 only when the most significant bit of the target M0 block is one, which means the first position of next block need to be deposited (match copy)
137
138        PHINode* phiCarryBit = b->CreatePHI(b->getInt64Ty(), 2);
139        PHINode* phiCurrentPosition = b->CreatePHI(b->getInt64Ty(), 2); // 0~4mb, and all M0 related
140        PHINode* phiCarryMatchOffset = b->CreatePHI(b->getSizeTy(), 2);
141
142        phiCarryBit->addIncoming(INT64_0, entryBlock);
143        phiCurrentPosition->addIncoming(INT64_0, entryBlock);
144        phiCarryMatchOffset->addIncoming(SIZE_0, entryBlock);
145
146        b->CreateLikelyCondBr(b->CreateICmpULT(phiCurrentPosition, itemsToDo), processLoopBody, processLoopExit);
147
148        // ---- ProcessLoopBody
149        b->SetInsertPoint(processLoopBody);
150
151        Value* dataBlockIndex = b->CreateUDiv(phiCurrentPosition, SIZE_64);
152        Value* currentInitM0 = b->CreateLoad(b->CreateGEP(m0MarkerBasePtr, dataBlockIndex));
153        vector<Value*> initSourceData = this->loadAllI64BitStreamValues(b, sourceStreamPtr, dataBlockIndex);
154
155        BasicBlock* carryBitProcessBlock = b->CreateBasicBlock("CarryBitProcessBlock");
156
157        BasicBlock* matchCopyLoopCon = b->CreateBasicBlock("MatchCopyLoopCon");
158        BasicBlock* matchCopyLoopBody = b->CreateBasicBlock("MatchCopyLoopBody");
159        BasicBlock* matchCopyLoopExit = b->CreateBasicBlock("MatchCopyLoopExit");
160
161        //
162        // The carry bit will need to be processed specially only when
163        // the most significant bit of previous block is 1 (the carry bit is 0x1) and the
164        // least significant bit of current block is 0
165        // e.g.
166        //   Assume the most significant bit is on the right side
167        //
168        //                    i64_1       i64_2
169        //   M0         ... 0000 0011 | 0111 0000 ...  - Carry bit need to be handle specially
170        //   M0         ... 0000 0011 | 1011 0000 ...  - Carry bit will be handle in the loop of i64_2
171        //   Carry Bit                  1000 0000 ...  - 0x1
172
173        Value* needProcessCarryBit = b->CreateAnd(phiCarryBit, b->CreateNot(b->CreateAnd(currentInitM0, b->getInt64(1))));
174        needProcessCarryBit = b->CreateICmpNE(needProcessCarryBit, INT64_0);
175
176        b->CreateUnlikelyCondBr(needProcessCarryBit, carryBitProcessBlock, matchCopyLoopCon);
177
178        // ---- CarryBitProcessBlock
179        b->SetInsertPoint(carryBitProcessBlock);
180        Value* carryCopyFromPos = b->CreateSub(phiCurrentPosition, phiCarryMatchOffset);
181        Value* carryCopyFromBlockIndex = b->CreateUDiv(carryCopyFromPos, SIZE_64);
182        Value* carryCopyFromOffset = b->CreateURem(carryCopyFromPos, SIZE_64);
183
184        vector<Value*> initSourceDataWithCarry = this->loadAllI64BitStreamValues(b, outputStreamPtr,
185                                                                                 carryCopyFromBlockIndex);
186
187        for (unsigned i = 0; i < mNumberOfStreams; i++) {
188            Value* v = initSourceDataWithCarry[i];
189            v = b->CreateLShr(v, carryCopyFromOffset);
190            v = b->CreateAnd(v, INT64_1);
191            initSourceDataWithCarry[i] = b->CreateOr(v, initSourceData[i]);
192        }
193        b->CreateBr(matchCopyLoopCon);
194
195        // ---- MatchCopyLoopCon
196        // MatchCopy Loop will handle one continuous data deposit each time
197        b->SetInsertPoint(matchCopyLoopCon);
198
199        PHINode* phiLatestMatchOffset = b->CreatePHI(b->getInt64Ty(), 3);
200        phiLatestMatchOffset->addIncoming(phiCarryMatchOffset, processLoopBody);
201        phiLatestMatchOffset->addIncoming(phiCarryMatchOffset, carryBitProcessBlock);
202
203        PHINode* phiRemainingM0Marker = b->CreatePHI(b->getInt64Ty(), 3);
204        phiRemainingM0Marker->addIncoming(currentInitM0, processLoopBody);
205        phiRemainingM0Marker->addIncoming(currentInitM0, carryBitProcessBlock);
206
207        std::vector<PHINode*> outputData;
208        for (unsigned i = 0; i < mNumberOfStreams; i++) {
209            PHINode* outputValue = b->CreatePHI(b->getInt64Ty(), 3);
210            outputValue->addIncoming(initSourceData[i], processLoopBody);
211            outputValue->addIncoming(initSourceDataWithCarry[i], carryBitProcessBlock);
212            outputData.push_back(outputValue);
213        }
214
215        b->CreateLikelyCondBr(b->CreateICmpNE(phiRemainingM0Marker, INT64_0), matchCopyLoopBody, matchCopyLoopExit);
216
217        // ---- MatchCopyLoopBody
218        b->SetInsertPoint(matchCopyLoopBody);
219
220        // Match Offset
221        // M0      0111 1000  - load new match offset
222        // M0      1100 0011  - use carryMatchOffset
223        Value* remainM0ForwardZero = b->CreateCountForwardZeroes(phiRemainingM0Marker);
224
225        BasicBlock* loadNextMatchOffsetBlock = b->CreateBasicBlock("loadNextMatchOffsetBlock");
226        BasicBlock* doMatchCopyBlock = b->CreateBasicBlock("DoMatchCopyBlock");
227
228        b->CreateLikelyCondBr(
229                b->CreateOr(b->CreateICmpEQ(phiLatestMatchOffset, INT64_0),
230                                   b->CreateICmpNE(remainM0ForwardZero, INT64_0)
231                ),
232                loadNextMatchOffsetBlock, doMatchCopyBlock
233        );
234
235        // ---- loadNextMatchOffsetBlock
236        b->SetInsertPoint(loadNextMatchOffsetBlock);
237        auto matchOffsetRet = this->loadNextMatchOffset(b);
238        BasicBlock* loadNextMatchOffsetExitBlock = b->GetInsertBlock();
239        Value* newMatchOffset = matchOffsetRet.first;
240        Value* newMatchOffsetPos = matchOffsetRet.second;
241        b->setScalarField("currentOffsetMarkerPos", newMatchOffsetPos);
242        b->setProcessedItemCount("MatchOffsetMarker", newMatchOffsetPos);
243        b->CreateBr(doMatchCopyBlock);
244
245        // ---- doMatchCopyBlock
246        b->SetInsertPoint(doMatchCopyBlock);
247
248        PHINode* phiTargetMatchOffset = b->CreatePHI(b->getSizeTy(), 2);
249        phiTargetMatchOffset->addIncoming(phiLatestMatchOffset, matchCopyLoopBody);
250        phiTargetMatchOffset->addIncoming(newMatchOffset, loadNextMatchOffsetExitBlock);
251
252        //
253        // M0            0011 0010
254        // boundary      0000 1000
255        // nextMask      0000 0111
256        // deposit       0011 1000
257        // newM0         0000 0010
258
259        Value* remainStart = b->CreateShl(INT64_1, remainM0ForwardZero);
260
261        Value* boundaryMarker = b->CreateAnd(b->CreateAdd(phiRemainingM0Marker, remainStart), b->CreateNot(phiRemainingM0Marker));
262
263        Value* nextMask = b->CreateSub(INT64_0, b->CreateShl(boundaryMarker, INT64_1));
264        Value* depositMarker = b->CreateAnd(
265                b->CreateOr(phiRemainingM0Marker, boundaryMarker),
266                b->CreateNot(nextMask)
267        );
268        Value* newM0Marker = b->CreateAnd(phiRemainingM0Marker, nextMask);
269        Value* depositMarkerPopcount = b->CreatePopcount(depositMarker);
270
271        Value* matchCopyFromStart = b->CreateSub(b->CreateAdd(phiCurrentPosition, remainM0ForwardZero), phiTargetMatchOffset);
272        Value* matchCopyFromBlockIndex = b->CreateUDiv(matchCopyFromStart, SIZE_64);
273
274        Value* matchCopyFromOffset = b->CreateURem(matchCopyFromStart, SIZE_64);
275        Value* matchCopyFromRemaining = b->CreateSub(SIZE_64, matchCopyFromOffset);
276        Value* matchCopyFromNextBlockIndex = b->CreateAdd(matchCopyFromBlockIndex, b->CreateSelect(b->CreateICmpULE(depositMarkerPopcount, matchCopyFromRemaining), SIZE_0, SIZE_1));
277
278
279        vector<Value*> fromBlockValues = this->loadAllI64BitStreamValues(b, outputStreamPtr, matchCopyFromBlockIndex);
280        vector<Value*> fromNextBlockValues = this->loadAllI64BitStreamValues(b, outputStreamPtr, matchCopyFromNextBlockIndex);
281
282        vector<Value*> pdepSourceData;
283        for (unsigned i = 0; i < mNumberOfStreams; i++) {
284            Value* fromBlockValue = fromBlockValues[i];
285            // when dataBlockIndex == matchCopyFromBlockIndex, we need to use current output value as input
286            fromBlockValue = b->CreateSelect(b->CreateICmpEQ(dataBlockIndex, matchCopyFromBlockIndex), outputData[i], fromBlockValue);
287            Value* fromNextBlockValue = fromNextBlockValues[i];
288            fromNextBlockValue = b->CreateSelect(b->CreateICmpEQ(dataBlockIndex, matchCopyFromNextBlockIndex), outputData[i], fromNextBlockValue);
289
290
291            Value * allFromValue = b->CreateOr(
292                    b->CreateLShr(fromBlockValue, matchCopyFromOffset),
293                    b->CreateShl(fromNextBlockValue, matchCopyFromRemaining)
294            );
295            pdepSourceData.push_back(allFromValue);
296        }
297
298
299        BasicBlock* doubleSourceDataCon = b->CreateBasicBlock("doubleSourceDataCon");
300        BasicBlock* doubleSourceDataBody = b->CreateBasicBlock("doubleSourceDataBody");
301        BasicBlock* doubleSourceDataExit = b->CreateBasicBlock("doubleSourceDataExit");
302
303        b->CreateBr(doubleSourceDataCon);
304
305        //
306        // When matchOffset < depositMarkerPopcount, we need to use log2 approach to double the source data
307        // e.g.
308        // Assume that match copy start position is 1, matchOffset is 1, match length is 5
309        //     outputBuffer              a000 0000 0000 0000
310        //     sourceDataBeforeDouble    a000 0000 0000 0000
311        // At this point, only 1 bit of source data is accessable, so it will double the source data 3 times until we have
312        // 1 * 2 ^ 3 = 8 bits accessable
313        //     sourceDataAfterDouble     aaaa aaaa 0000 0000
314        //     outputBuffer(after copy)  aaaa aa00 0000 0000
315        //
316
317        // ---- doubleSourceDataCon
318        b->SetInsertPoint(doubleSourceDataCon);
319        PHINode* phiSourceDataAccessable = b->CreatePHI(b->getSizeTy(), 2);
320        phiSourceDataAccessable->addIncoming(phiTargetMatchOffset, doMatchCopyBlock);
321        vector<PHINode*> phiPdepSourceData;
322        for (unsigned i = 0; i < mNumberOfStreams; i++) {
323            PHINode* v = b->CreatePHI(b->getInt64Ty(), 2);
324            v->addIncoming(pdepSourceData[i], doMatchCopyBlock);
325            phiPdepSourceData.push_back(v);
326        }
327        b->CreateUnlikelyCondBr(b->CreateICmpULT(phiSourceDataAccessable, depositMarkerPopcount), doubleSourceDataBody, doubleSourceDataExit);
328
329        // ---- doubleSourceDataBody
330        b->SetInsertPoint(doubleSourceDataBody);
331        for (unsigned i = 0; i < mNumberOfStreams; i++) {
332            PHINode* v = phiPdepSourceData[i];
333            Value* newValue = b->CreateOr(v, b->CreateShl(v, phiSourceDataAccessable));
334            v->addIncoming(newValue, doubleSourceDataBody);
335        }
336        phiSourceDataAccessable->addIncoming(b->CreateShl(phiSourceDataAccessable, SIZE_1), doubleSourceDataBody);
337
338        b->CreateBr(doubleSourceDataCon);
339
340        // ---- doubleSourceDataExit
341        b->SetInsertPoint(doubleSourceDataExit);
342        // At this point, we can guarantee we have enough data for pdep
343        for (unsigned i = 0; i < mNumberOfStreams; i++) {
344            // Do Match Copy by PDEP
345            Value* source_field = phiPdepSourceData[i];
346            Value * newValue = b->CreateCall(PDEP_func, {source_field, depositMarker});
347            PHINode* outputValue = outputData[i];
348            Value* newOutputValue = b->CreateOr(outputValue, newValue);
349            outputValue->addIncoming(newOutputValue, b->GetInsertBlock());
350        }
351        phiRemainingM0Marker->addIncoming(newM0Marker, b->GetInsertBlock());
352        phiLatestMatchOffset->addIncoming(phiTargetMatchOffset, b->GetInsertBlock());
353
354        b->CreateBr(matchCopyLoopCon);
355
356        // ---- MatchCopyLoopExit
357        b->SetInsertPoint(matchCopyLoopExit);
358        this->storeAllI64BitStreamValues(b, outputStreamPtr, dataBlockIndex, outputData);
359
360        Value* hasNewCarryBit = b->CreateAnd(currentInitM0, b->CreateShl(INT64_1, b->getInt64(63)));
361        hasNewCarryBit = b->CreateICmpNE(hasNewCarryBit, INT64_0);
362        Value* newCarryBit = b->CreateSelect(hasNewCarryBit, INT64_1, INT64_0);
363        phiCarryBit->addIncoming(newCarryBit, b->GetInsertBlock());
364
365        phiCarryMatchOffset->addIncoming(b->CreateSelect(hasNewCarryBit, phiLatestMatchOffset, b->getSize(0)), b->GetInsertBlock());
366
367        phiCurrentPosition->addIncoming(b->CreateAdd(phiCurrentPosition, SIZE_64), b->GetInsertBlock());
368
369        b->CreateBr(processLoopCon);
370
371        // ---- ProcessLoopExit
372        b->SetInsertPoint(processLoopExit);
373        Value * const toProcessItemCount = b->CreateAdd(processed, itemsToDo);
374        b->setProcessedItemCount("M0Marker", toProcessItemCount);
375        b->CreateBr(exitBlock);
376
377        // ---- ExitBlock
378        b->SetInsertPoint(exitBlock);
379    }
380
381    void LZ4BitStreamMatchCopyKernel::storeAllI64BitStreamValues(const std::unique_ptr<KernelBuilder> &b,
382                                                                       llvm::Value *basePtr, llvm::Value *i64PackIndex,
383                                                                       const std::vector<llvm::PHINode *> &values) {
384        // TODO PHINode here is a workaround
385        // For now, assume bit block type is always <4 * i64>
386        Value* bitBlockIndex = b->CreateUDiv(i64PackIndex, b->getSize(4));
387        Value* extractIndex = b->CreateURem(i64PackIndex, b->getSize(4));
388
389        for (unsigned i = 0; i < mNumberOfStreams; i++) {
390            Value* bitBlockPtr =  b->CreateGEP(basePtr, b->CreateAdd(b->CreateMul(bitBlockIndex, b->getSize(mNumberOfStreams)), b->getSize(i)));
391            bitBlockPtr = b->CreatePointerCast(bitBlockPtr, b->getInt64Ty()->getPointerTo());
392            b->CreateStore(values[i], b->CreateGEP(bitBlockPtr, extractIndex));
393        }
394
395    }
396
397    LZ4BitStreamMatchCopyKernel::LZ4BitStreamMatchCopyKernel(const std::unique_ptr<kernel::KernelBuilder> & iBuilder, unsigned numberOfStreams, std::string name)
398            : SegmentOrientedKernel(std::move(name),
399// Inputs
400                                    {
401                                            Binding{iBuilder->getStreamSetTy(1, 1), "MatchOffsetMarker", BoundedRate(0, 1)},
402                                            Binding{iBuilder->getStreamSetTy(1, 1), "M0Marker", BoundedRate(0, 1)},
403                                            Binding{iBuilder->getStreamSetTy(1, 8), "byteStream", RateEqualTo("MatchOffsetMarker")},
404                                            Binding{iBuilder->getStreamSetTy(numberOfStreams, 1), "inputBitStream",
405                                                    RateEqualTo("M0Marker")},
406                                    },
407// Outputs
408                                    {
409                                            Binding{iBuilder->getStreamSetTy(numberOfStreams, 1), "outputBitStream",
410                                                    RateEqualTo("M0Marker")}
411                                    },
412// Arguments
413                                    {
414                                    },
415                                    {},
416                                    {
417                    Binding(iBuilder->getSizeTy(), "currentOffsetMarkerPos"),
418            })
419            , mNumberOfStreams(numberOfStreams) {
420
421        setStride(4 * 1024 * 1024);
422        addAttribute(MustExplicitlyTerminate());
423    }
424
425}
Note: See TracBrowser for help on using the repository browser.